diff options
author | Igor Pashev <igor.pashev@nexenta.com> | 2012-06-29 14:36:07 +0400 |
---|---|---|
committer | Igor Pashev <igor.pashev@nexenta.com> | 2012-06-29 14:36:07 +0400 |
commit | e0463df9c3d2ee6155221cc443c571d5da47098a (patch) | |
tree | 5c6b99e64c1b65d986e2722728c74f202a578be6 | |
download | sunmake-e0463df9c3d2ee6155221cc443c571d5da47098a.tar.gz |
Initial import of DevPro make sourcesorig
Downloaded from http://dlc.sun.com/osol/devpro/downloads/current/
Licensed under CDDL http://www.opensource.org/licenses/CDDL-1.0
134 files changed, 35979 insertions, 0 deletions
@@ -0,0 +1,110 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)README.usr 1.10 06/12/18 +# + +Enclosed in this directory tree is the source code for "make". + +Three different "build" options are supported. + +1. To build the executable itself: + + Set up your environment variables, and then run "./build". + + For example, in "sh", you could use this command: + + cd usr/src; STUDIOBIN=/your/path/to/Sun/Studio/bin \ + DESTDIR=/your/path/to/root/of/install/location \ + ./build + + The resulting files, listed below, will be installed under $DESTDIR. + + The default values for these environment variables are: + + STUDIOBIN=/opt/SUNWspro/bin + DESTDIR=../../destdir/root_`uname -p` + + If you're happy with the default values, there is no need to specify any. + + Also, the following derived variables can be set individually if so desired. + The default values are listed below for reference: + + CC=$(STUDIOBIN)/cc + CCC=$(STUDIOBIN)/CC + MAKE=$(STUDIOBIN)/dmake -m serial + + Note that only Sun Studio 10 or Sun Studio 11 compilers are supported. + + List of created files: + + $DESTDIR/usr/lib/libmakestate.so.1 + $DESTDIR/usr/lib/amd64/libmakestate.so.1 OR $DESTDIR/usr/lib/sparcv9/libmakestate.so.1 + $DESTDIR/usr/lib/svr4.make + $DESTDIR/usr/share/lib/make/svr4.make.rules + $DESTDIR/usr/share/lib/make/make.rules + $DESTDIR/usr/ccs/bin/make + $DESTDIR/usr/xpg4/bin/make + +2. To build a "binaries only" release image: + + Set up your environment variables, and then run "./build_bin_img". + + For example, in "sh", you could use this command: + + cd usr/src; STUDIOBIN=/your/path/to/Sun/Studio/bin \ + DESTDIR=/your/path/to/root/of/install/location \ + BINIMGFILE=/your/path/to/binaries-only/imagefile \ + ./build_bin_img + + As in (1) above, the make executables are built under the control + of a handful of environment variables, and installed at $DESTDIR. + + The files at $DESTDIR are then collected into a tarball, which is + is stored at $BINIMGFILE.bz2 + + The default value for BINIMGFILE is + + devpro-make-open-bins-{date}.{arch}.tar + + Where "date" is in the format "YYYYMMDD", and "arch" is either + "i386" or "sparc". + +3. To build a "source code" release image: + + Set up your environment variable, and then run "./build_src_img". + + For example, in "sh", you could use this command: + + cd usr/src; SRCIMGFILE=/your/path/to/source-code/imagefile \ + ./build_src_img + + The entire source tree is collected into a tarball, which is + is stored at $SRCIMGFILE.bz2 + + The default value for SRCIMGFILE is: + + SRCIMGFILE=../../imgdir/devpro-make-src-{date}.tar + + Where "date" is in the format "YYYYMMDD". + diff --git a/ReleaseNotes b/ReleaseNotes new file mode 100644 index 0000000..40be009 --- /dev/null +++ b/ReleaseNotes @@ -0,0 +1,51 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)ReleaseNotes 1.6 06/11/03 +# + +A tarball is supplied which contains the source code for "make." + + % ls + devpro-make-src-20061002.tar.bz2 + +To unpack this tarball: + + % bunzip2 devpro-make-src-20061002.tar.bz2 + % ls + devpro-make-src-20061002.tar + % tar xf devpro-make-src-20061002.tar + % ls -F + README + ReleaseNotes + devpro-make-src-20061002.tar + usr/ + % + +The file "ReleaseNotes" is this document itself. + +The file "README" contains more information on building and installing +this code. + +The code source tree, and scripts to manage it, are included under the +"./usr/src/" directory. diff --git a/usr/src/OPENSOLARIS.LICENSE b/usr/src/OPENSOLARIS.LICENSE new file mode 100644 index 0000000..8ce4411 --- /dev/null +++ b/usr/src/OPENSOLARIS.LICENSE @@ -0,0 +1,242 @@ + COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) + Version 1.0 + + +1. Definitions. + + 1.1. “Contributor” means each individual or entity that creates or contributes to the creation of Modifications. + + 1.2. “Contributor Version” means the combination of the Original Software, prior Modifications used by a Contributor + (if any), and the Modifications made by that particular Contributor. + + 1.3. “Covered Software” means (a) the Original Software, or (b) Modifications, or (c) the combination + of files containing Original Software with files containing Modifications, in each case including portions thereof. + + 1.4. “Executable” means the Covered Software in any form other than Source Code. + + 1.5. “Initial Developer” means the individual or entity that first makes Original Software available under this License. + + 1.6. “Larger Work” means a work which combines Covered Software or portions thereof with code not governed by the terms + of this License. + + 1.7. “License” means this document. + + 1.8. “Licensable” means having the right to grant, to the maximum extent possible, whether at the time of the + initial grant or subsequently acquired, any and all of the rights conveyed herein. + + 1.9. “Modifications” means the Source Code and Executable form of any of the following: + A. Any file that results from an addition to, deletion from or modification of the contents of a file + containing Original Software or previous Modifications; + B. Any new file that contains any part of the Original Software or previous Modification; or + C. Any new file that is contributed or otherwise made available under the terms of this License. + + 1.10. “Original Software” means the Source Code and Executable form of computer software code that is originally + released under this License. + + 1.11. “Patent Claims” means any patent claim(s), now owned or hereafter acquired, including without limitation, + method, process, and apparatus claims, in any patent Licensable by grantor. + + 1.12. “Source Code” means (a) the common form of computer software code in which modifications are made and + (b) associated documentation included in or with such code. + + 1.13. “You” (or “Your”) means an individual or a legal entity exercising rights under, and complying with all of + the terms of, this License. For legal entities, “You” includes any entity which controls, is controlled by, or is + under common control with You. For purposes of this definition, “control” means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more + than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. + +2. License Grants. + + 2.1. The Initial Developer Grant. + Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, + the Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license: + + (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer, + to use, reproduce, modify, display, perform, sublicense and distribute the Original Software (or portions + thereof), with or without Modifications, and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using or selling of Original Software, to make, have made, + use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Software (or portions thereof). + + (c) The licenses granted in Sections 2.1(a) and (b) are effective on the date Initial Developer first + distributes or otherwise makes the Original Software available to a third party under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is granted: (1) for code that You delete from + the Original Software, or (2) for infringements caused by: (i) the modification of the Original Software, + or (ii) the combination of the Original Software with other software or devices. + + 2.2. Contributor Grant. + Conditioned upon Your compliance with Section 3.1 below and subject to third party intellectual property claims, + each Contributor hereby grants You a world-wide, royalty-free, non-exclusive license: + + (a) under intellectual property rights (other than patent or trademark) Licensable by Contributor to use, + reproduce, modify, display, perform, sublicense and distribute the Modifications created by such Contributor + (or portions thereof), either on an unmodified basis, with other Modifications, as Covered Software and/or + as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or selling of Modifications made by that Contributor + either alone and/or in combination with its Contributor Version (or portions of such combination), to make, + use, sell, offer for sale, have made, and/or otherwise dispose of: (1) Modifications made by that Contributor + (or portions thereof); and (2) the combination of Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) The licenses granted in Sections 2.2(a) and 2.2(b) are effective on the date Contributor first distributes + or otherwise makes the Modifications available to a third party. + + (d) Notwithstanding Section 2.2(b) above, no patent license is granted: (1) for any code that Contributor has + deleted from the Contributor Version; (2) for infringements caused by: (i) third party modifications of + Contributor Version, or (ii) the combination of Modifications made by that Contributor with other software + (except as part of the Contributor Version) or other devices; or (3) under Patent Claims infringed by Covered + Software in the absence of Modifications made by that Contributor. + +3. Distribution Obligations. + + 3.1. Availability of Source Code. + Any Covered Software that You distribute or otherwise make available in Executable form must also be made available + in Source Code form and that Source Code form must be distributed only under the terms of this License. You must + include a copy of this License with every copy of the Source Code form of the Covered Software You distribute or + otherwise make available. You must inform recipients of any such Covered Software in Executable form as to how they + can obtain such Covered Software in Source Code form in a reasonable manner on or through a medium customarily used + for software exchange. + + 3.2. Modifications. + The Modifications that You create or to which You contribute are governed by the terms of this License. You + represent that You believe Your Modifications are Your original creation(s) and/or You have sufficient rights to + grant the rights conveyed by this License. + + 3.3. Required Notices. + You must include a notice in each of Your Modifications that identifies You as the Contributor of the Modification. + You may not remove or alter any copyright, patent or trademark notices contained within the Covered Software, or + any notices of licensing or any descriptive text giving attribution to any Contributor or the Initial Developer. + + 3.4. Application of Additional Terms. + You may not offer or impose any terms on any Covered Software in Source Code form that alters or restricts the + applicable version of this License or the recipients’ rights hereunder. You may choose to offer, and to charge a + fee for, warranty, support, indemnity or liability obligations to one or more recipients of Covered Software. + However, you may do so only on Your own behalf, and not on behalf of the Initial Developer or any Contributor. + You must make it absolutely clear that any such warranty, support, indemnity or liability obligation is offered + by You alone, and You hereby agree to indemnify the Initial Developer and every Contributor for any liability + incurred by the Initial Developer or such Contributor as a result of warranty, support, indemnity or liability + terms You offer. + + 3.5. Distribution of Executable Versions. + You may distribute the Executable form of the Covered Software under the terms of this License or under the terms + of a license of Your choice, which may contain terms different from this License, provided that You are in compliance + with the terms of this License and that the license for the Executable form does not attempt to limit or alter + the recipient’s rights in the Source Code form from the rights set forth in this License. If You distribute the + Covered Software in Executable form under a different license, You must make it absolutely clear that any terms + which differ from this License are offered by You alone, not by the Initial Developer or Contributor. You hereby + agree to indemnify the Initial Developer and every Contributor for any liability incurred by the Initial Developer + or such Contributor as a result of any such terms You offer. + + 3.6. Larger Works. + You may create a Larger Work by combining Covered Software with other code not governed by the terms of this License + and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this + License are fulfilled for the Covered Software. + +4. Versions of the License. + + 4.1. New Versions. + Sun Microsystems, Inc. is the initial license steward and may publish revised and/or new versions of this License + from time to time. Each version will be given a distinguishing version number. Except as provided in Section 4.3, + no one other than the license steward has the right to modify this License. + + 4.2. Effect of New Versions. + You may always continue to use, distribute or otherwise make the Covered Software available under the terms of + the version of the License under which You originally received the Covered Software. If the Initial Developer + includes a notice in the Original Software prohibiting it from being distributed or otherwise made available under + any subsequent version of the License, You must distribute and make the Covered Software available under the terms + of the version of the License under which You originally received the Covered Software. Otherwise, You may also + choose to use, distribute or otherwise make the Covered Software available under the terms of any subsequent version + of the License published by the license steward. + + 4.3. Modified Versions. + When You are an Initial Developer and You want to create a new license for Your Original Software, You may create + and use a modified version of this License if You: (a) rename the license and remove any references to the name of + the license steward (except to note that the license differs from this License); and (b) otherwise make it clear that + the license contains terms which differ from this License. + +5. DISCLAIMER OF WARRANTY. + +COVERED SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN “AS IS” BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR +IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE COVERED SOFTWARE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A +PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED SOFTWARE IS WITH YOU. +SHOULD ANY COVERED SOFTWARE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE +COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. +NO USE OF ANY COVERED SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +6. TERMINATION. + + 6.1. This License and the rights granted hereunder will terminate automatically if You fail to comply with terms + herein and fail to cure such breach within 30 days of becoming aware of the breach. Provisions which, by their + nature, must remain in effect beyond the termination of this License shall survive. + + 6.2. If You assert a patent infringement claim (excluding declaratory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom You assert such claim is referred to as + “Participant”) alleging that the Participant Software (meaning the Contributor Version where the Participant + is a Contributor or the Original Software where the Participant is the Initial Developer) directly or + indirectly infringes any patent, then any and all rights granted directly or indirectly to You by such Participant, + the Initial Developer (if the Initial Developer is not the Participant) and all Contributors under Sections 2.1 + and/or 2.2 of this License shall, upon 60 days notice from Participant terminate prospectively and automatically + at the expiration of such 60 day notice period, unless if within such 60 day period You withdraw Your claim with + respect to the Participant Software against such Participant either unilaterally or pursuant to a written agreement + with Participant. + + 6.3. If You assert a patent infringement claim against Participant alleging that the Participant Software directly + or indirectly infringes any patent where such claim is resolved (such as by license or settlement) prior to the + initiation of patent infringement litigation, then the reasonable value of the licenses granted by such Participant + under Sections 2.1 or 2.2 shall be taken into account in determining the amount or value of any payment or license. + + 6.4. In the event of termination under Sections 6.1 or 6.2 above, all end user licenses that have been validly granted + by You or any distributor hereunder prior to termination (excluding licenses granted to You by any distributor) + shall survive termination. + +7. LIMITATION OF LIABILITY. + +UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE +INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED SOFTWARE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO +ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR +LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY +SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL +INJURY RESULTING FROM SUCH PARTY’S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +8. U.S. GOVERNMENT END USERS. + +The Covered Software is a “commercial item,” as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), consisting of +“commercial computer software” (as that term is defined at 48 C.F.R. § 252.227-7014(a)(1)) and “commercial computer software documentation” +as such terms are used in 48 C.F.R. 12.212 Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), +all U.S. Government End Users acquire Covered Software with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, +and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this License. + +9. MISCELLANEOUS. + +This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed +by the law of the jurisdiction specified in a notice contained within the Original Software (except to the extent applicable law, if any, +provides otherwise), excluding such jurisdiction’s conflict-of-law provisions. Any litigation relating to this License shall be subject +to the jurisdiction of the courts located in the jurisdiction and venue specified in a notice contained within the Original Software, with the +losing party responsible for costs, including, without limitation, court costs and reasonable attorneys’ fees and expenses. The application of +the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that +the language of a contract shall be construed against the drafter shall not apply to this License. You agree that You alone are responsible for +compliance with the United States export administration regulations (and the export control laws and regulation of any other countries) when You use, +distribute or otherwise make available any Covered Software. + +10. RESPONSIBILITY FOR CLAIMS. + +As between Initial Developer and the Contributors, each party is responsible for claims and damages arising, directly or indirectly, out of +its utilization of rights under this License and You agree to work with Initial Developer and Contributors to distribute such responsibility on +an equitable basis. Nothing herein is intended or shall be deemed to constitute any admission of liability. + +-------- + +NOTICE PURSUANT TO SECTION 9 OF THE COMMON DEVELOPMENT AND DISTRIBUTION +LICENSE (CDDL) + +The OpenSolaris code released under the CDDL shall be governed by the laws +of the State of California (excluding conflict-of-law provisions). Any +litigation relating to this License shall be subject to the jurisdiction of +the Federal Courts of the Northern District of California and the state +courts of the State of California, with venue lying in Santa Clara County, +California. + diff --git a/usr/src/build b/usr/src/build new file mode 100755 index 0000000..967f5af --- /dev/null +++ b/usr/src/build @@ -0,0 +1,127 @@ +#!/bin/csh -f +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)build 1.15 06/12/18 +# + + +# This script compiles the "make" sources to produce a "make" +# executable. +# +# See also "./README" for a description of its use. +# +# +# Optional environment variables: +# +# name typical use description +# +# STUDIOBIN $STUDIOBIN/cc installation of the Sun Studio compilers +# CC $CC -c x.c preferred C compiler +# CCC $CCC -c x.cc preferred C++ compiler +# MAKE $MAKE {target} preferred "make" executable +# DESTDIR $DESTDIR/usr/ccs root of installation tree + +# Legal arguments are "clean", "all", and "install". The default +# is "install". + +set erruse = 0 + +if ( $#argv == 0 ) then + set args = ( install ) +else if ( $#argv == 1 ) then + if ( ( $argv[1] == clean ) || ( $argv[1] == all ) || ( $argv[1] == install ) ) then + set args = ( $argv ) + else + set erruse = 1 + endif +else + set erruse = 1 +endif + +if ( $erruse ) then + echo 'usage: build [ clean | all | install ]' + exit 0 +endif + +# Set up environment variables. User-supplied values are respected. +# If the variable is not set by the user, a default is supplied. +# If CC, CCC, or MAKE are not set, they are derived from STUDIOBIN + +if ( ! $?STUDIOBIN ) then + setenv STUDIOBIN /opt/SUNWspro/bin +endif + +if ( ! $?CC ) then + setenv CC ${STUDIOBIN}/cc +endif + +if ( ! $?CCC ) then + setenv CCC ${STUDIOBIN}/CC +endif + +if ( ! $?MAKE ) then + setenv MAKE "${STUDIOBIN}/dmake -m serial" +endif + +setenv CC64 $CC +setenv CCC64 $CCC + +if ( ! $?DESTDIR ) then + setenv DESTDIR ../../destdir/root_`uname -p` +endif + +# Ensure that $DESTDIR exists, and is absolute. + +if ( ! -d $DESTDIR ) then + mkdir -p $DESTDIR +endif + +set p = `pwd` +cd $DESTDIR +setenv DESTDIR `pwd` +cd $p + +cd ./make_src + +# Do the build itself, using .../make_src/Makefile. + +echo +echo === starting build === +echo +echo Using variables: +echo +echo ' 'CC = $CC +echo ' 'CCC = $CCC +echo ' 'DESTDIR = $DESTDIR +echo ' 'MAKE = $MAKE +echo ' 'STUDIOBIN = $STUDIOBIN +echo +$MAKE CC=${CC} CCC=${CCC} DESTDIR=${DESTDIR} MAKE=${MAKE} $args +echo +echo === build complete === +echo +echo Binaries installed at $DESTDIR':' +echo +cd $DESTDIR +find . -type f -print | sed 's/^/ /' diff --git a/usr/src/build_bin_img b/usr/src/build_bin_img new file mode 100755 index 0000000..d48f75b --- /dev/null +++ b/usr/src/build_bin_img @@ -0,0 +1,108 @@ +#!/bin/csh -f +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)build_bin_img 1.18 06/12/18 +# + + +# This script creates a "tarball" distribution image of the "make" executable. +# +# See also "./README" for a description of its use. +# +# +# Optional environment variables: +# +# name typical use description +# +# DESTDIR $DESTDIR/usr/ccs root of installation tree +# BINIMGFILE $BINIMGFILE''.bz2 bzipped tarball image + + +if ( $#argv > 0 ) then + echo 'usage: build_bin_img' + exit 0 +endif + +# Set up environment variables. User-supplied values are respected. +# If the variable is not set by the user, a default is supplied. + +if ( ! $?DESTDIR ) then + setenv DESTDIR ../../destdir/root_`uname -p` +endif + +if ( ! $?BINIMGFILE ) then + setenv BINIMGFILE ../../imgdir/devpro-make-open-bins-`/usr/bin/date -u +'%'Y'%'m'%'d`.`uname -p`.tar +endif + +# Compile the sources to produce the "make" binaries. See "./README" +# for details. + +./build + +# Ensure that the path to $BINIMGFILE exists, and is absolute. + +set t = $BINIMGFILE + +if ( Z$BINIMGFILE =~ Z*/* ) then + set bifd = $t:h + set bifn = $t:t +else + set bifd = . + set bifn = $t +endif + +mkdir -p $bifd + +set p = `pwd` +cd $bifd +setenv BINIMGFILE `pwd`/$bifn +cd $p + +# Ensure that $DESTDIR is absolute. + +set p = `pwd` +cd $DESTDIR +setenv DESTDIR `pwd` +cd $p + +echo +echo === starting build of binary image === +echo +echo Using variables: +echo +echo ' 'DESTDIR = $DESTDIR +echo ' 'BINIMGFILE = $BINIMGFILE + +# Create and compress the "tarball". + +rm -f $BINIMGFILE $BINIMGFILE''.bz2 + +tar cf $BINIMGFILE -C $DESTDIR . + +bzip2 $BINIMGFILE + +echo +echo === build of binary image complete === +echo +ls -l $BINIMGFILE''* diff --git a/usr/src/build_src_img b/usr/src/build_src_img new file mode 100755 index 0000000..212d6f0 --- /dev/null +++ b/usr/src/build_src_img @@ -0,0 +1,93 @@ +#!/bin/csh -f +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)build_src_img 1.13 06/12/13 +# + + +# This script creates a "tarball" distribution image of the "make" source code. +# +# See also "./README" for a description of its use +# +# +# Optional environment variables: +# +# name typical use description +# +# SRCIMGFILE $SRCIMGFILE''.bz2 bzipped tarball image + +if ( $#argv > 0 ) then + echo 'usage: build_src_img' + exit 0 +endif + +# Set up environment variable. User-supplied value is respected. +# If the variable is not set by the user, a default is supplied. + +if ( ! $?SRCIMGFILE ) then + setenv SRCIMGFILE ../../imgdir/devpro-make-src-`/usr/bin/date -u +'%'Y'%'m'%'d`.tar +endif + +# Ensure that the path to $SRCIMGFILE exists, and is absolute. + +set t = $SRCIMGFILE + +if ( Z$t =~ Z*/* ) then + set sifd = $t:h + set sifn = $t:t +else + set sifd = . + set sifn = $t +endif + +if ( ! -d $sifd ) then + mkdir -p $sifd +endif + +set p = `pwd` +cd $sifd +setenv SRCIMGFILE `pwd`/$sifn +cd $p + +echo +echo === starting build of source image === +echo +echo Using variable: +echo +echo ' 'SRCIMGFILE = $SRCIMGFILE + +# Create and compress the "tarball". + +cd ../.. + +rm -f $SRCIMGFILE $SRCIMGFILE''.bz2 + +tar cf $SRCIMGFILE ./README ./ReleaseNotes ./usr/src + +bzip2 $SRCIMGFILE + +echo +echo === build of source image complete === +echo +ls -l $SRCIMGFILE''* diff --git a/usr/src/make_src/Make/Makefile b/usr/src/make_src/Make/Makefile new file mode 100644 index 0000000..886d661 --- /dev/null +++ b/usr/src/make_src/Make/Makefile @@ -0,0 +1,34 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.21 06/12/12 +# + +TOP = .. + +SUBDIRS= lib \ + bin \ + localize \ + man + +include ${TOP}/rules/recurse.mk diff --git a/usr/src/make_src/Make/bin/Makefile b/usr/src/make_src/Make/bin/Makefile new file mode 100644 index 0000000..a210f0e --- /dev/null +++ b/usr/src/make_src/Make/bin/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.16 06/12/12 +# + +TOP = ../.. + +# SUBDIRS = make maketool rxm rxs +SUBDIRS = make rxm rxs + +include $(TOP)/rules/recurse.mk diff --git a/usr/src/make_src/Make/bin/make/Common.mk b/usr/src/make_src/Make/bin/make/Common.mk new file mode 100644 index 0000000..bf00849 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/Common.mk @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Common.mk 1.3 06/12/12 +# + +TOP = ../../../../.. +include $(TOP)/rules/master.mk + +PKG_TOP = $(TOP)/Make + +LIBBSD_DIR = $(PKG_TOP)/libbsd +LIBBSD = $(LIBBSD_DIR)/$(VARIANT)/libbsd.a + +LIBMKSDMSI18N_DIR = $(PKG_TOP)/libmksdmsi18n +LIBMKSDMSI18N = $(LIBMKSDMSI18N_DIR)/$(VARIANT)/libmksdmsi18n.a + +LIBMKSH_DIR = $(PKG_TOP)/libmksh +LIBMKSH = $(LIBMKSH_DIR)/$(VARIANT)/libmksh.a + +LIBVROOT_DIR = $(PKG_TOP)/libvroot +LIBVROOT = $(LIBVROOT_DIR)/$(VARIANT)/libvroot.a + +SRC = ../src +include $(TOP)/rules/derived.mk + diff --git a/usr/src/make_src/Make/bin/make/Makefile b/usr/src/make_src/Make/bin/make/Makefile new file mode 100644 index 0000000..58d212c --- /dev/null +++ b/usr/src/make_src/Make/bin/make/Makefile @@ -0,0 +1,32 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1997 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.7 06/12/12 +# + +TOP = ../../.. + +#SUBDIRS = dmake localize +SUBDIRS = smake make.xpg4 make.svr4 + +include $(TOP)/rules/recurse.mk diff --git a/usr/src/make_src/Make/bin/make/common/ar.cc b/usr/src/make_src/Make/bin/make/common/ar.cc new file mode 100644 index 0000000..dfd0362 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/ar.cc @@ -0,0 +1,908 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)ar.cc 1.28 06/12/12 + */ + +#pragma ident "@(#)ar.cc 1.28 06/12/12" + +/* + * ar.c + * + * Deal with the lib.a(member.o) and lib.a((entry-point)) notations + * + * Look inside archives for notations a(b) and a((b)) + * a(b) is file member b in archive a + * a((b)) is entry point b in object archive a + * + * For 6.0, create a make which can understand all archive + * formats. This is kind of tricky, and <ar.h> isnt any help. + */ + +/* + * Included files + */ +#include <avo/avo_alloca.h> /* alloca() */ +#include <ar.h> +#include <errno.h> /* errno */ +#include <fcntl.h> /* open() */ +#include <mk/defs.h> +#include <mksh/misc.h> /* retmem_mb() */ + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) +struct ranlib { + union { + off_t ran_strx; /* string table index of */ + char *ran_name; /* symbol defined by */ + } ran_un; + off_t ran_off; /* library member at this offset */ +}; +#else +#include <ranlib.h> +#endif + +#if defined(linux) +#include <ctype.h> /* isspace */ +#else +#include <unistd.h> /* close() */ +#endif + + +/* + * Defined macros + */ +#ifndef S5EMUL +#undef BITSPERBYTE +#define BITSPERBYTE 8 +#endif + +/* + * Defines for all the different archive formats. See next comment + * block for justification for not using <ar.h>s versions. + */ +#define AR_5_MAGIC "<ar>" /* 5.0 format magic string */ +#define AR_5_MAGIC_LENGTH 4 /* 5.0 format string length */ + +#define AR_PORT_MAGIC "!<arch>\n" /* Port. (6.0) magic string */ +#define AR_PORT_MAGIC_LENGTH 8 /* Port. (6.0) string length */ +#define AR_PORT_END_MAGIC "`\n" /* Port. (6.0) end of header */ +#define AR_PORT_WORD 4 /* Port. (6.0) 'word' length */ + +/* + * typedefs & structs + */ +/* + * These are the archive file headers for the formats. Note + * that it really doesnt matter if these structures are defined + * here. They are correct as of the respective archive format + * releases. If the archive format is changed, then since backwards + * compatability is the desired behavior, a new structure is added + * to the list. + */ +typedef struct { /* 5.0 ar header format: vax family; 3b family */ + char ar_magic[AR_5_MAGIC_LENGTH]; /* AR_5_MAGIC*/ + char ar_name[16]; /* Space terminated */ + char ar_date[AR_PORT_WORD]; /* sgetl() accessed */ + char ar_syms[AR_PORT_WORD]; /* sgetl() accessed */ +} Arh_5; + +typedef struct { /* 5.0 ar symbol format: vax family; 3b family */ + char sym_name[8]; /* Space terminated */ + char sym_ptr[AR_PORT_WORD]; /* sgetl() accessed */ +} Ars_5; + +typedef struct { /* 5.0 ar member format: vax family; 3b family */ + char arf_name[16]; /* Space terminated */ + char arf_date[AR_PORT_WORD]; /* sgetl() accessed */ + char arf_uid[AR_PORT_WORD]; /* sgetl() accessed */ + char arf_gid[AR_PORT_WORD]; /* sgetl() accessed */ + char arf_mode[AR_PORT_WORD]; /* sgetl() accessed */ + char arf_size[AR_PORT_WORD]; /* sgetl() accessed */ +} Arf_5; + +typedef struct { /* Portable (6.0) ar format: vax family; 3b family */ + char ar_name[16]; /* Space terminated */ + /* left-adjusted fields; decimal ascii; blank filled */ + char ar_date[12]; + char ar_uid[6]; + char ar_gid[6]; + char ar_mode[8]; /* octal ascii */ + char ar_size[10]; + /* special end-of-header string (AR_PORT_END_MAGIC) */ + char ar_fmag[2]; +} Ar_port; + +enum ar_type { + AR_5, + AR_PORT +}; + +typedef unsigned int ar_port_word; // must be 4-bytes long + +typedef struct { + FILE *fd; + /* to distiguish ar format */ + enum ar_type type; + /* where first ar member header is at */ + long first_ar_mem; + /* where the symbol lookup starts */ + long sym_begin; + /* the number of symbols available */ + long num_symbols; + /* length of symbol directory file */ + long sym_size; + Arh_5 arh_5; + Ars_5 ars_5; + Arf_5 arf_5; + Ar_port ar_port; +} Ar; + +/* + * Static variables + */ + +/* + * File table of contents + */ +extern timestruc_t& read_archive(register Name target); +static Boolean open_archive(char *filename, register Ar *arp); +static void close_archive(register Ar *arp); +static Boolean read_archive_dir(register Ar *arp, Name library, char **long_names_table); +static void translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table); +static long sgetl(char *); + +/* + * read_archive(target) + * + * Read the contents of an ar file. + * + * Return value: + * The time the member was created + * + * Parameters: + * target The member to find time for + * + * Global variables used: + * empty_name The Name "" + */ + +int read_member_header (Ar_port *header, FILE *fd, char* filename); +int process_long_names_member (register Ar *arp, char **long_names_table, char *filename); + +timestruc_t& +read_archive(register Name target) +{ + register Property member; + wchar_t *slash; + String_rec true_member_name; + wchar_t buffer[STRING_BUFFER_LENGTH]; + register Name true_member = NULL; + Ar ar; + char *long_names_table = NULL; /* Table of long + member names */ + + member = get_prop(target->prop, member_prop); + /* + * Check if the member has directory component. + * If so, remove the dir and see if we know the date. + */ + if (member->body.member.member != NULL) { + Wstring member_string(member->body.member.member); + wchar_t * wcb = member_string.get_string(); + if((slash = (wchar_t *) wsrchr(wcb, (int) slash_char)) != NULL) { + INIT_STRING_FROM_STACK(true_member_name, buffer); + append_string(member->body.member.library->string_mb, + &true_member_name, + FIND_LENGTH); + append_char((int) parenleft_char, &true_member_name); + append_string(slash + 1, &true_member_name, FIND_LENGTH); + append_char((int) parenright_char, &true_member_name); + true_member = GETNAME(true_member_name.buffer.start, + FIND_LENGTH); + if (true_member->stat.time != file_no_time) { + target->stat.time = true_member->stat.time; + return target->stat.time; + } + } + } + if (open_archive(member->body.member.library->string_mb, &ar) == failed) { + if (errno == ENOENT) { + target->stat.stat_errno = ENOENT; + close_archive(&ar); + if (member->body.member.member == NULL) { + member->body.member.member = empty_name; + } + return target->stat.time = file_doesnt_exist; + } else { + fatal(catgets(catd, 1, 1, "Can't access archive `%s': %s"), + member->body.member.library->string_mb, + errmsg(errno)); + } + } + if (target->stat.time == file_no_time) { + if (read_archive_dir(&ar, member->body.member.library, + &long_names_table) + == failed){ + fatal(catgets(catd, 1, 2, "Can't access archive `%s': %s"), + member->body.member.library->string_mb, + errmsg(errno)); + } + } + if (member->body.member.entry != NULL) { + translate_entry(&ar, target, member,&long_names_table); + } + close_archive(&ar); + if (long_names_table) { + retmem_mb(long_names_table); + } + if (true_member != NULL) { + target->stat.time = true_member->stat.time; + } + if (target->stat.time == file_no_time) { + target->stat.time = file_doesnt_exist; + } + return target->stat.time; +} + +/* + * open_archive(filename, arp) + * + * Return value: + * Indicates if open failed or not + * + * Parameters: + * filename The name of the archive we need to read + * arp Pointer to ar file description block + * + * Global variables used: + */ +static Boolean +open_archive(char *filename, register Ar *arp) +{ + int fd; + char mag_5[AR_5_MAGIC_LENGTH]; + char mag_port[AR_PORT_MAGIC_LENGTH]; + char buffer[4]; + + arp->fd = NULL; + fd = open_vroot(filename, O_RDONLY, 0, NULL, VROOT_DEFAULT); + if ((fd < 0) || ((arp->fd = fdopen(fd, "r")) == NULL)) { + return failed; + } + (void) fcntl(fileno(arp->fd), F_SETFD, 1); + +#if !defined(SUN5_0) && !defined(linux) //XXX + /* Read enough of the archive to distinguish between the formats */ + if (fread(mag_5, AR_5_MAGIC_LENGTH, 1, arp->fd) != 1) { + return failed; + } + if (IS_EQUALN(mag_5, AR_5_MAGIC, AR_5_MAGIC_LENGTH)) { + arp->type = AR_5; + /* Must read in header to set necessary info */ + if (fseek(arp->fd, 0L, 0) != 0 || + fread((char *) &arp->arh_5, sizeof (Arh_5), 1, arp->fd) != + 1) { + return failed; + } + arp->sym_begin = ftell(arp->fd); + arp->num_symbols = sgetl(arp->arh_5.ar_syms); + arp->first_ar_mem = arp->sym_begin + + sizeof (Ars_5) * arp->num_symbols; + arp->sym_size = 0L; + return succeeded; + } + if (fseek(arp->fd, 0L, 0) != 0) { + return failed; + } +#endif + if (fread(mag_port, AR_PORT_MAGIC_LENGTH, 1, arp->fd) != 1) { + return failed; + } + if (IS_EQUALN(mag_port, AR_PORT_MAGIC, AR_PORT_MAGIC_LENGTH)) { + arp->type = AR_PORT; + /* + * Read in first member header to find out if there is + * a symbol definition table. + */ + + int ret = read_member_header(&arp->ar_port, arp->fd, filename); + if (ret == failed) { + return failed; + } else if(ret == -1) { + /* There is no member header - empty archive */ + arp->sym_size = arp->num_symbols = arp->sym_begin = 0L; + arp->first_ar_mem = ftell(arp->fd); + return succeeded; + } + /* + * The following values are the default if there is + * no symbol directory and long member names. + */ + arp->sym_size = arp->num_symbols = arp->sym_begin = 0L; + arp->first_ar_mem = ftell(arp->fd) - (long) sizeof (Ar_port); + + /* + * Do we have a symbol table? A symbol table is always + * the first member in an archive. In 4.1.x it has the + * name __.SYMDEF, in SVr4, it has the name "/ " + */ +/* +#ifdef SUN5_0 + MBSTOWCS(wcs_buffer, NOCATGETS("/ ")); + if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) { +#else + MBSTOWCS(wcs_buffer, NOCATGETS("__.SYMDEF ")); + if (IS_WEQUALN(arp->ar_port.ar_name, wcs_buffer, 16)) { +#endif + */ +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + if (IS_EQUALN(arp->ar_port.ar_name, + NOCATGETS("/ "), + 16)) { +#else + if (IS_EQUALN(arp->ar_port.ar_name, + NOCATGETS("__.SYMDEF "), + 16)) { +#endif + if (sscanf(arp->ar_port.ar_size, + "%ld", + &arp->sym_size) != 1) { + return failed; + } + arp->sym_size += (arp->sym_size & 1); /* round up */ + if (fread(buffer, sizeof buffer, 1, arp->fd) != 1) { + return failed; + } + arp->num_symbols = sgetl(buffer); + arp->sym_begin = ftell(arp->fd); + arp->first_ar_mem = arp->sym_begin + + arp->sym_size - sizeof buffer; + } + return succeeded; + } + fatal(catgets(catd, 1, 3, "`%s' is not an archive"), filename); + /* NOTREACHED */ + return failed; +} + + +/* + * close_archive(arp) + * + * Parameters: + * arp Pointer to ar file description block + * + * Global variables used: + */ +static void +close_archive(register Ar *arp) +{ + if (arp->fd != NULL) { + (void) fclose(arp->fd); + } +} + +/* + * read_archive_dir(arp, library, long_names_table) + * + * Reads the directory of an archive and enters all + * the members into the make symboltable in lib(member) format + * with their dates. + * + * Parameters: + * arp Pointer to ar file description block + * library Name of lib to enter members for. + * Used to form "lib(member)" string. + * long_names_table table that contains list of members + * with names > 15 characters long + * + * Global variables used: + */ +static Boolean +#if defined(SUN5_0) || defined(linux) //XXX +read_archive_dir(register Ar *arp, Name library, char **long_names_table) +#else +read_archive_dir(register Ar *arp, Name library, char **) +#endif +{ + wchar_t *name_string; + wchar_t *member_string; + register long len; + register wchar_t *p; + register char *q; + register Name name; + Property member; + long ptr; + long date; + +#if defined(SUN5_0) || defined(linux) //XXX + int offset; + + /* + * If any of the members has a name > 15 chars, + * it will be found here. + */ + if (process_long_names_member(arp, long_names_table, library->string_mb) == failed) { + return failed; + } +#endif + name_string = ALLOC_WC((int) (library->hash.length + + (int) ar_member_name_len * 2)); + (void) mbstowcs(name_string, library->string_mb, (int) library->hash.length); + member_string = name_string + library->hash.length; + *member_string++ = (int) parenleft_char; + + if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) { + goto read_error; + } + /* Read the directory using the appropriate format */ + switch (arp->type) { + case AR_5: + for (;;) { + if (fread((char *) &arp->arf_5, sizeof arp->arf_5, 1, arp->fd) + != 1) { + if (feof(arp->fd)) { + return succeeded; + } + break; + } + len = sizeof arp->arf_5.arf_name; + for (p = member_string, q = arp->arf_5.arf_name; + (len > 0) && (*q != (int) nul_char) && !isspace(*q); + ) { + MBTOWC(p, q); + p++; + q++; + } + *p++ = (int) parenright_char; + *p = (int) nul_char; + name = GETNAME(name_string, FIND_LENGTH); + /* + * [tolik] Fix for dmake bug 1234018. + * If name->stat.time is already set, then it should not + * be changed. (D)make propogates time stamp for one + * member, and when it calls exists() for another member, + * the first one may be changed. + */ + if(name->stat.time == file_no_time) { + name->stat.time.tv_sec = sgetl(arp->arf_5.arf_date); + name->stat.time.tv_nsec = LONG_MAX; + } + name->is_member = library->is_member; + member = maybe_append_prop(name, member_prop); + member->body.member.library = library; + *--p = (int) nul_char; + if (member->body.member.member == NULL) { + member->body.member.member = + GETNAME(member_string, FIND_LENGTH); + } + ptr = sgetl(arp->arf_5.arf_size); + ptr += (ptr & 1); + if (fseek(arp->fd, ptr, 1) != 0) { + goto read_error; + } + } + break; + case AR_PORT: + for (;;) { + if ((fread((char *) &arp->ar_port, + sizeof arp->ar_port, + 1, + arp->fd) != 1) || + !IS_EQUALN(arp->ar_port.ar_fmag, + AR_PORT_END_MAGIC, + sizeof arp->ar_port.ar_fmag)) { + if (feof(arp->fd)) { + return succeeded; + } + fatal( + catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"), + library->string_mb, + ftell(arp->fd) + ); + } +#if defined(SUN5_0) || defined(linux) //XXX + /* If it's a long name, retrieve it from long name table */ + if (arp->ar_port.ar_name[0] == '/') { + /* + * "len" is used for hashing the string. + * We're using "ar_member_name_len" instead of + * the actual name length since it's the longest + * string the "ar" command can handle at this + * point. + */ + len = ar_member_name_len; + sscanf(arp->ar_port.ar_name + 1, + "%ld", + &offset); + q = *long_names_table + offset; + } else { + q = arp->ar_port.ar_name; + len = sizeof arp->ar_port.ar_name; + } +#else + q = arp->ar_port.ar_name; + len = sizeof arp->ar_port.ar_name; +#endif + + for (p = member_string; + (len > 0) && + (*q != (int) nul_char) && + !isspace(*q) && + (*q != (int) slash_char); + ) { + MBTOWC(p, q); + p++; + q++; + } + *p++ = (int) parenright_char; + *p = (int) nul_char; + name = GETNAME(name_string, FIND_LENGTH); + name->is_member = library->is_member; + member = maybe_append_prop(name, member_prop); + member->body.member.library = library; + *--p = (int) nul_char; + if (member->body.member.member == NULL) { + member->body.member.member = + GETNAME(member_string, FIND_LENGTH); + } + if (sscanf(arp->ar_port.ar_date, "%ld", &date) != 1) { + WCSTOMBS(mbs_buffer, name_string); + fatal(catgets(catd, 1, 4, "Bad date field for member `%s' in archive `%s'"), + mbs_buffer, + library->string_mb); + } + /* + * [tolik] Fix for dmake bug 1234018. + */ + if(name->stat.time == file_no_time) { + name->stat.time.tv_sec = date; + name->stat.time.tv_nsec = LONG_MAX; + } + if (sscanf(arp->ar_port.ar_size, "%ld", &ptr) != 1) { + WCSTOMBS(mbs_buffer, name_string); + fatal(catgets(catd, 1, 5, "Bad size field for member `%s' in archive `%s'"), + mbs_buffer, + library->string_mb); + } + ptr += (ptr & 1); + if (fseek(arp->fd, ptr, 1) != 0) { + goto read_error; + } + } + break; + } + + /* Only here if fread() [or IS_EQUALN()] failed and not at EOF */ +read_error: + fatal(catgets(catd, 1, 6, "Read error in archive `%s': %s"), + library->string_mb, + errmsg(errno)); + /* NOTREACHED */ +} + + +/* + * process_long_names_member(arp) + * + * If the archive contains members with names longer + * than 15 characters, then it has a special member + * with the name "// " that contains a table + * of null-terminated long names. This member + * is always the first member, after the symbol table + * if it exists. + * + * Parameters: + * arp Pointer to ar file description block + * + * Global variables used: + */ +int +process_long_names_member(register Ar *arp, char **long_names_table, char *filename) +{ + Ar_port *ar_member_header; + int table_size; + + if (fseek(arp->fd, arp->first_ar_mem, 0) != 0) { + return failed; + } + if ((ar_member_header = + (Ar_port *) alloca((int) sizeof(Ar_port))) == NULL){ + perror(catgets(catd, 1, 7, "memory allocation failure")); + return failed; + } + int ret = read_member_header(ar_member_header, arp->fd, filename); + if (ret == failed) { + return failed; + } else if(ret == -1) { + /* There is no member header - empty archive */ + return succeeded; + } + /* Do we have special member containing long names? */ + if (IS_EQUALN(ar_member_header->ar_name, + NOCATGETS("// "), + 16)){ + if (sscanf(ar_member_header->ar_size, + "%ld", + &table_size) != 1) { + return failed; + } + *long_names_table = (char *) malloc(table_size); + /* Read the list of long member names into the table */ + if (fread(*long_names_table, table_size, 1, arp->fd) != 1) { + return failed; + } + arp->first_ar_mem = ftell(arp->fd); + } + return succeeded; +} + +/* + * translate_entry(arp, target, member) + * + * Finds the member for one lib.a((entry)) + * + * Parameters: + * arp Pointer to ar file description block + * target Target to find member name for + * member Property to fill in with info + * + * Global variables used: + */ +static void +translate_entry(register Ar *arp, Name target, register Property member, char **long_names_table) +{ + register int len; + register int i; + wchar_t *member_string; + ar_port_word *offs; + int strtablen; + char *syms; /* string table */ + char *csym; /* string table */ + ar_port_word *offend; /* end of offsets table */ + int date; + register wchar_t *ap; + register char *hp; + int maxs; + int offset; + char buffer[4]; + + if (arp->sym_begin == 0L || arp->num_symbols == 0L) { + fatal(catgets(catd, 1, 8, "Cannot find symbol `%s' in archive `%s'"), + member->body.member.entry->string_mb, + member->body.member.library->string_mb); + } + + if (fseek(arp->fd, arp->sym_begin, 0) != 0) { + goto read_error; + } + member_string = ALLOC_WC((int) ((int) ar_member_name_len * 2)); + + switch (arp->type) { + case AR_5: + if ((len = member->body.member.entry->hash.length) > 8) { + len = 8; + } + for (i = 0; i < arp->num_symbols; i++) { + if (fread((char *) &arp->ars_5, + sizeof arp->ars_5, + 1, + arp->fd) != 1) { + goto read_error; + } + if (IS_EQUALN(arp->ars_5.sym_name, + member->body.member.entry->string_mb, + len)) { + if ((fseek(arp->fd, + sgetl(arp->ars_5.sym_ptr), + 0) != 0) || + (fread((char *) &arp->arf_5, + sizeof arp->arf_5, + 1, + arp->fd) != 1)) { + goto read_error; + } + MBSTOWCS(wcs_buffer, arp->arf_5.arf_name); + (void) wsncpy(member_string, + wcs_buffer, + wslen(wcs_buffer)); + member_string[sizeof(arp->arf_5.arf_name)] = + (int) nul_char; + member->body.member.member = + GETNAME(member_string, FIND_LENGTH); + target->stat.time.tv_sec = sgetl(arp->arf_5.arf_date); + target->stat.time.tv_nsec = LONG_MAX; + return; + } + } + break; + case AR_PORT: + offs = (ar_port_word *) alloca((int) (arp->num_symbols * AR_PORT_WORD)); + if (fread((char *) offs, + AR_PORT_WORD, + (int) arp->num_symbols, + arp->fd) != arp->num_symbols) { + goto read_error; + } + + for(i=0;i<arp->num_symbols;i++) { + *((int*)buffer)=offs[i]; + offs[i]=(ar_port_word)sgetl(buffer); + } + + strtablen=arp->sym_size-4-(int) (arp->num_symbols * AR_PORT_WORD); + syms = (char *) alloca(strtablen); + if (fread(syms, + sizeof (char), + strtablen, + arp->fd) != strtablen) { + goto read_error; + } + offend = &offs[arp->num_symbols]; + while (offs < offend) { + maxs = strlen(member->body.member.entry->string_mb); + if(strlen(syms) > maxs) + maxs = strlen(syms); + if (IS_EQUALN(syms, + member->body.member.entry->string_mb, + maxs)) { + if (fseek(arp->fd, + (long) *offs, + 0) != 0) { + goto read_error; + } + if ((fread((char *) &arp->ar_port, + sizeof arp->ar_port, + 1, + arp->fd) != 1) || + !IS_EQUALN(arp->ar_port.ar_fmag, + AR_PORT_END_MAGIC, + sizeof arp->ar_port.ar_fmag)) { + goto read_error; + } + if (sscanf(arp->ar_port.ar_date, + "%ld", + &date) != 1) { + fatal(catgets(catd, 1, 9, "Bad date field for member `%s' in archive `%s'"), + arp->ar_port.ar_name, + target->string_mb); + } +#if defined(SUN5_0) || defined(linux) //XXX + /* If it's a long name, retrieve it from long name table */ + if (arp->ar_port.ar_name[0] == '/') { + sscanf(arp->ar_port.ar_name + 1, + "%ld", + &offset); + len = ar_member_name_len; + hp = *long_names_table + offset; + } else { + len = sizeof arp->ar_port.ar_name; + hp = arp->ar_port.ar_name; + } +#else + hp = arp->ar_port.ar_name; +#endif + ap = member_string; + while (*hp && + (*hp != (int) slash_char) && + (ap < &member_string[len])) { + MBTOWC(ap, hp); + ap++; + hp++; + } + *ap = (int) nul_char; + member->body.member.member = + GETNAME(member_string, FIND_LENGTH); + target->stat.time.tv_sec = date; + target->stat.time.tv_nsec = LONG_MAX; + return; + } + offs++; + while(*syms!='\0') syms++; + syms++; + } + } + fatal(catgets(catd, 1, 10, "Cannot find symbol `%s' in archive `%s'"), + member->body.member.entry->string_mb, + member->body.member.library->string_mb); + /*NOTREACHED*/ + +read_error: + if (ferror(arp->fd)) { + fatal(catgets(catd, 1, 11, "Read error in archive `%s': %s"), + member->body.member.library->string_mb, + errmsg(errno)); + } else { + fatal(catgets(catd, 1, 12, "Read error in archive `%s': Premature EOF"), + member->body.member.library->string_mb); + } +} + +/* + * sgetl(buffer) + * + * The intent here is to provide a means to make the value of + * bytes in an io-buffer correspond to the value of a long + * in the memory while doing the io a long at a time. + * Files written and read in this way are machine-independent. + * + * Return value: + * Long int read from buffer + * Parameters: + * buffer buffer we need to read long int from + * + * Global variables used: + */ +static long +sgetl(register char *buffer) +{ + register long w = 0; + register int i = BITSPERBYTE * AR_PORT_WORD; + + while ((i -= BITSPERBYTE) >= 0) { + w |= (long) ((unsigned char) *buffer++) << i; + } + return w; +} + + +/* + * read_member_header(header, fd, filename) + * + * reads the member header for the 4.1.x and SVr4 archives. + * + * Return value: + * fails if read error or member + * header is not the right format + * Parameters: + * header There's one before each archive member + * fd file descriptor for the archive file. + * + * Global variables used: + */ +int +read_member_header(Ar_port *header, FILE *fd, char* filename) +{ + int num = fread((char *) header, sizeof (Ar_port), 1, fd); + if (num != 1 && feof(fd)) { + /* There is no member header - empty archive */ + return -1; + } + if ((num != 1) || + !IS_EQUALN( + AR_PORT_END_MAGIC, + header->ar_fmag, + sizeof (header->ar_fmag) + ) + ) { + fatal( + catgets(catd, 1, 28, "Read error in archive `%s': invalid archive file member header at 0x%x"), + filename, + ftell(fd) + ); + } + return succeeded; +} + diff --git a/usr/src/make_src/Make/bin/make/common/default.mk.file b/usr/src/make_src/Make/bin/make/common/default.mk.file new file mode 100644 index 0000000..6128d35 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/default.mk.file @@ -0,0 +1,231 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1993 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)default.mk.file 1.4 06/12/12 +# + +SUFFIXES = .o .c .c~ .cc .cc~ .s .s~ .S .S~ .ln .f .f~ .F .F~ .l .l~ \ + .mod .mod~ .sym .def .def~ .p .p~ .r .r~ .y .y~ .h .h~ .sh .sh~ \ + .cps .cps~ +.SUFFIXES: $(SUFFIXES) + +# OUTPUT_OPTION should be defined to "-o $@" when +# the default rules are used for non-local files. +OUTPUT_OPTION= + +# C language section. +CC=cc +CFLAGS= +CPPFLAGS= +LINT=lint +LINTFLAGS= +COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -target $(TARGET_ARCH:-%=%) -c +LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -target $(TARGET_ARCH:-%=%) +LINT.c=$(LINT) $(LINTFLAGS) $(CPPFLAGS) $(TARGET_ARCH) +.c: + $(LINK.c) -o $@ $< $(LDLIBS) +.c.ln: + $(LINT.c) $(OUTPUT_OPTION) -i $< +.c.o: + $(COMPILE.c) $(OUTPUT_OPTION) $< +.c.a: + $(COMPILE.c) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# C language section. yacc. +YACC=yacc +YFLAGS= +YACC.y=$(YACC) $(YFLAGS) +.y: + $(YACC.y) $< + $(LINK.c) -o $@ y.tab.c $(LDLIBS) + $(RM) y.tab.c +.y.c: + $(YACC.y) $< + mv y.tab.c $@ +.y.ln: + $(YACC.y) $< + $(LINT.c) -o $@ -i y.tab.c + $(RM) y.tab.c +.y.o: + $(YACC.y) $< + $(COMPILE.c) -o $@ y.tab.c + $(RM) y.tab.c + +# C language section. lex. +LEX=lex +LFLAGS= +LEX.l=$(LEX) $(LFLAGS) -t +.l: + $(RM) $*.c + $(LEX.l) $< > $*.c + $(LINK.c) -o $@ $*.c -ll $(LDLIBS) + $(RM) $*.c +.l.c : + $(RM) $@ + $(LEX.l) $< > $@ +.l.ln: + $(RM) $*.c + $(LEX.l) $< > $*.c + $(LINT.c) -o $@ -i $*.c + $(RM) $*.c +.l.o: + $(RM) $*.c + $(LEX.l) $< > $*.c + $(COMPILE.c) -o $@ $*.c + $(RM) $*.c + +# C++ language section. +CCC=CC +CCFLAGS= +COMPILE.cc=$(CCC) $(CCFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.cc=$(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) +.cc: + $(LINK.cc) -o $@ $< $(LDLIBS) +.cc.o: + $(COMPILE.cc) $(OUTPUT_OPTION) $< +.cc.a: + $(COMPILE.cc) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# FORTRAN section. +FC=f77 +FFLAGS= +COMPILE.f=$(FC) $(FFLAGS) $(TARGET_ARCH) -c +LINK.f=$(FC) $(FFLAGS) $(LDFLAGS) $(TARGET_ARCH) +COMPILE.F=$(FC) $(FFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.F=$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) +.f: + $(LINK.f) -o $@ $< $(LDLIBS) +.f.o: + $(COMPILE.f) $(OUTPUT_OPTION) $< +.f.a: + $(COMPILE.f) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.F: + $(LINK.F) -o $@ $< $(LDLIBS) +.F.o: + $(COMPILE.F) $(OUTPUT_OPTION) $< +.F.a: + $(COMPILE.F) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# FORTRAN section. ratfor. +RFLAGS= +COMPILE.r=$(FC) $(FFLAGS) $(RFLAGS) $(TARGET_ARCH) -c +LINK.r=$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) $(TARGET_ARCH) +.r: + $(LINK.r) -o $@ $< $(LDLIBS) +.r.o: + $(COMPILE.r) $(OUTPUT_OPTION) $< +.r.a: + $(COMPILE.r) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Modula-2 section. +M2C=m2c +M2FLAGS= +MODFLAGS= +DEFFLAGS= +COMPILE.def=$(M2C) $(M2FLAGS) $(DEFFLAGS) $(TARGET_ARCH) +COMPILE.mod=$(M2C) $(M2FLAGS) $(MODFLAGS) $(TARGET_ARCH) +.def.sym: + $(COMPILE.def) -o $@ $< +.mod: + $(COMPILE.mod) -o $@ -e $@ $< +.mod.o: + $(COMPILE.mod) -o $@ $< +.mod.a: + $(COMPILE.mod) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Pascal section. +PC=pc +PFLAGS= +COMPILE.p=$(PC) $(PFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +LINK.p=$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) +.p: + $(LINK.p) -o $@ $< $(LDLIBS) +.p.o: + $(COMPILE.p) $(OUTPUT_OPTION) $< +.p.a: + $(COMPILE.p) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Assembly section. +AS=as +ASFLAGS= +COMPILE.s=$(AS) $(ASFLAGS) $(TARGET_MACH) +COMPILE.S=$(CC) $(ASFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c +.s.o: + $(COMPILE.s) -o $@ $< +.s.a: + $(COMPILE.s) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.S.o: + $(COMPILE.S) -o $@ $< +.S.a: + $(COMPILE.S) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Shell section. +.sh: + $(RM) $@ + cat $< > $@ + chmod +x $@ + +# NeWS section +CPS=cps +CPSFLAGS= +.cps.h: + $(CPS) $(CPSFLAGS) $*.cps + +# Miscellaneous section. +LD=ld +LDFLAGS= +LDLIBS= +MAKE=make +RM=rm -f +AR=ar +ARFLAGS=rv +GET=/usr/sccs/get +GFLAGS= + +markfile.o: markfile + echo "static char _sccsid[] = \"`grep @'(#)' markfile`\";" > markfile.c + cc -c markfile.c + $(RM) markfile.c + +SCCSFLAGS= +SCCSGETFLAGS=-s +.SCCS_GET: + sccs $(SCCSFLAGS) get $(SCCSGETFLAGS) $@ -G$@ diff --git a/usr/src/make_src/Make/bin/make/common/depvar.cc b/usr/src/make_src/Make/bin/make/common/depvar.cc new file mode 100644 index 0000000..ee4be87 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/depvar.cc @@ -0,0 +1,149 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1995 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)depvar.cc 1.14 06/12/12 + */ + +#pragma ident "@(#)depvar.cc 1.14 06/12/12" + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/misc.h> /* getmem() */ + +/* + * This file deals with "Dependency Variables". + * The "-V var" command line option is used to indicate + * that var is a dependency variable. Used in conjunction with + * the -P option the user is asking if the named variables affect + * the dependencies of the given target. + */ + +struct _Depvar { + Name name; /* Name of variable */ + struct _Depvar *next; /* Linked list */ + Boolean cmdline; /* Macro defined on the cmdline? */ +}; + +typedef struct _Depvar *Depvar; + +static Depvar depvar_list; +static Depvar *bpatch = &depvar_list; +static Boolean variant_deps; + +/* + * Add a name to the list. + */ + +void +depvar_add_to_list(Name name, Boolean cmdline) +{ + Depvar dv; + +#ifdef SUNOS4_AND_AFTER + dv = ALLOC(Depvar); +#else + dv = (Depvar) Malloc(sizeof(struct _Depvar)); +#endif + dv->name = name; + dv->next = NULL; + dv->cmdline = cmdline; + *bpatch = dv; + bpatch = &dv->next; +} + +/* + * The macro `name' has been used in either the left-hand or + * right-hand side of a dependency. See if it is in the + * list. Two things are looked for. Names given as args + * to the -V list are checked so as to set the same/differ + * output for the -P option. Names given as macro=value + * command-line args are checked and, if found, an NSE + * warning is produced. + */ +void +depvar_dep_macro_used(Name name) +{ + Depvar dv; + + for (dv = depvar_list; dv != NULL; dv = dv->next) { + if (name == dv->name) { +#ifdef NSE +#ifdef SUNOS4_AND_AFTER + if (dv->cmdline) { +#else + if (is_true(dv->cmdline)) { +#endif + nse_dep_cmdmacro(dv->name->string); + } +#endif + variant_deps = true; + break; + } + } +} + +#ifdef NSE +/* + * The macro `name' has been used in either the argument + * to a cd before a recursive make. See if it was + * defined on the command-line and, if so, complain. + */ +void +depvar_rule_macro_used(Name name) +{ + Depvar dv; + + for (dv = depvar_list; dv != NULL; dv = dv->next) { + if (name == dv->name) { +#ifdef SUNOS4_AND_AFTER + if (dv->cmdline) { +#else + if (is_true(dv->cmdline)) { +#endif + nse_rule_cmdmacro(dv->name->string); + } + break; + } + } +} +#endif + +/* + * Print the results. If any of the Dependency Variables + * affected the dependencies then the dependencies potentially + * differ because of these variables. + */ +void +depvar_print_results(void) +{ + if (variant_deps) { + printf(catgets(catd, 1, 234, "differ\n")); + } else { + printf(catgets(catd, 1, 235, "same\n")); + } +} + diff --git a/usr/src/make_src/Make/bin/make/common/dist.cc b/usr/src/make_src/Make/bin/make/common/dist.cc new file mode 100644 index 0000000..f825d43 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/dist.cc @@ -0,0 +1,581 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)dist.cc 1.35 06/12/12 + */ + +#pragma ident "@(#)dist.cc 1.25 96/03/12" + +#ifdef DISTRIBUTED +/* + * dist.cc + * + * Deal with the distributed processing + */ + +#include <avo/err.h> +#include <avo/find_dir.h> +#include <avo/util.h> +#include <dm/Avo_AcknowledgeMsg.h> +#include <dm/Avo_DoJobMsg.h> +#include <dm/Avo_JobResultMsg.h> +#include <mk/defs.h> +#include <mksh/misc.h> /* getmem() */ +#include <rw/pstream.h> +#include <rw/queuecol.h> +#include <rw/xdrstrea.h> +#include <signal.h> +#ifdef linux +#include <sstream> +using namespace std; +#else +#include <strstream.h> +#endif +#include <sys/stat.h> /* stat() */ +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> +#include <errno.h> + +/* + * Defined macros + */ + +#define AVO_BLOCK_INTERUPTS sigfillset(&newset) ; \ + sigprocmask(SIG_SETMASK, &newset, &oldset) + +#define AVO_UNBLOCK_INTERUPTS \ + sigprocmask(SIG_SETMASK, &oldset, &newset) + + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +int dmake_ifd; +FILE* dmake_ifp; +XDR xdrs_in; + +int dmake_ofd; +FILE* dmake_ofp; +XDR xdrs_out; + +// These instances are required for the RWfactory. +static Avo_JobResultMsg dummyJobResultMsg; +static Avo_AcknowledgeMsg dummyAcknowledgeMsg; +static int firstAcknowledgeReceived = 0; + +int rxmPid = 0; + +/* + * File table of contents + */ +static void set_dmake_env_vars(void); + +/* + * void + * startup_rxm(void) + * + * When startup_rxm() is called, read_command_options() and + * read_files_and_state() have already been read, so DMake + * will now know what options to pass to rxm. + * + * rxm + * [ -k ] [ -n ] + * [ -c <dmake_rcfile> ] + * [ -g <dmake_group> ] + * [ -j <dmake_max_jobs> ] + * [ -m <dmake_mode> ] + * [ -o <dmake_odir> ] + * <read_fd> <write_fd> + * + * rxm will, among other things, read the rc file. + * + */ +void +startup_rxm(void) +{ + Name dmake_name; + Name dmake_value; + Avo_err *find_run_dir_err; + int pipe1[2], pipe2[2]; + Property prop; + char *run_dir; + char rxm_command[MAXPATHLEN]; + int rxm_debug = 0; + + int length; + char * env; + + firstAcknowledgeReceived = 0; + /* + * Create two pipes, one for dmake->rxm, and one for rxm->dmake. + * pipe1 is dmake->rxm, + * pipe2 is rxm->dmake. + */ + if ((pipe(pipe1) < 0) || (pipe(pipe2) < 0)) { + fatal(catgets(catd, 1, 245, "pipe() failed: %s"), errmsg(errno)); + } + + set_dmake_env_vars(); + + if ((rxmPid = fork()) < 0) { /* error */ + fatal(catgets(catd, 1, 246, "fork() failed: %s"), errmsg(errno)); + } else if (rxmPid > 0) { /* parent, dmake */ + dmake_ofd = pipe1[1]; // write side of pipe + if (!(dmake_ofp = fdopen(dmake_ofd, "a"))) { + fatal(catgets(catd, 1, 247, "fdopen() failed: %s"), errmsg(errno)); + } + xdrstdio_create(&xdrs_out, dmake_ofp, XDR_ENCODE); + + dmake_ifd = pipe2[0]; // read side of pipe + if (!(dmake_ifp = fdopen(dmake_ifd, "r"))) { + fatal(catgets(catd, 1, 248, "fdopen() failed: %s"), errmsg(errno)); + } + xdrstdio_create(&xdrs_in, dmake_ifp, XDR_DECODE); + + close(pipe1[0]); // read side + close(pipe2[1]); // write side + } else { /* child, rxm */ + close(pipe1[1]); // write side + close(pipe2[0]); // read side + + /* Find the run directory of dmake, for rxm. */ + find_run_dir_err = avo_find_run_dir(&run_dir); + if (find_run_dir_err) { + delete find_run_dir_err; + /* Use the path to find rxm. */ + (void) sprintf(rxm_command, NOCATGETS("rxm")); + } else { + /* Use the run dir of dmake for rxm. */ + (void) sprintf(rxm_command, NOCATGETS("%s/rxm"), run_dir); + } + + if (continue_after_error) { + (void) strcat(rxm_command, NOCATGETS(" -k")); + } + if (do_not_exec_rule) { + (void) strcat(rxm_command, NOCATGETS(" -n")); + } + if (rxm_debug) { + (void) strcat(rxm_command, NOCATGETS(" -S")); + } + if (send_mtool_msgs) { + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" -O %d"), + mtool_msgs_fd); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" -c %s"), + dmake_value->string_mb); + } else { + length = 2 + strlen(NOCATGETS("DMAKE_RCFILE")); + env = getmem(length); + (void) sprintf(env, + "%s=", + NOCATGETS("DMAKE_RCFILE")); + (void) putenv(env); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" -g %s"), + dmake_value->string_mb); + } else { + length = 2 + strlen(NOCATGETS("DMAKE_GROUP")); + env = getmem(length); + (void) sprintf(env, + "%s=", + NOCATGETS("DMAKE_GROUP")); + (void) putenv(env); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" -j %s"), + dmake_value->string_mb); + } else { + length = 2 + strlen(NOCATGETS("DMAKE_MAX_JOBS")); + env = getmem(length); + (void) sprintf(env, + "%s=", + NOCATGETS("DMAKE_MAX_JOBS")); + (void) putenv(env); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" -m %s"), + dmake_value->string_mb); + } else { + length = 2 + strlen(NOCATGETS("DMAKE_MODE")); + env = getmem(length); + (void) sprintf(env, + "%s=", + NOCATGETS("DMAKE_MODE")); + (void) putenv(env); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" -o %s"), + dmake_value->string_mb); + } else { + length = 2 + strlen(NOCATGETS("DMAKE_ODIR")); + env = getmem(length); + (void) sprintf(env, + "%s=", + NOCATGETS("DMAKE_ODIR")); + (void) putenv(env); + } + + (void) sprintf(&rxm_command[strlen(rxm_command)], + NOCATGETS(" %d %d"), + pipe1[0], pipe2[1]); +#ifdef linux + execl(NOCATGETS("/bin/sh"), +#else + execl(NOCATGETS("/usr/bin/sh"), +#endif + NOCATGETS("sh"), + NOCATGETS("-c"), + rxm_command, + (char *)NULL); + _exit(127); + } +} + +/* + * static void + * set_dmake_env_vars() + * + * Sets the DMAKE_* environment variables for rxm and rxs. + * DMAKE_PWD + * DMAKE_NPWD + * DMAKE_UMASK + * DMAKE_SHELL + */ +static void +set_dmake_env_vars() +{ + char *current_netpath; + char *current_path; + static char *env; + int length; + char netpath[MAXPATHLEN]; + mode_t um; + char um_buf[MAXPATHLEN]; + Name dmake_name; + Name dmake_value; + Property prop; + +#ifdef REDIRECT_ERR + /* Set __DMAKE_REDIRECT_STDERR */ + length = 2 + strlen(NOCATGETS("__DMAKE_REDIRECT_STDERR")) + 1; + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("__DMAKE_REDIRECT_STDERR"), + out_err_same ? NOCATGETS("0") : NOCATGETS("1")); + (void) putenv(env); +#endif + + /* Set DMAKE_PWD to the current working directory */ + current_path = get_current_path(); + length = 2 + strlen(NOCATGETS("DMAKE_PWD")) + strlen(current_path); + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("DMAKE_PWD"), + current_path); + (void) putenv(env); + + /* Set DMAKE_NPWD to machine:pathname */ + if (avo_path_to_netpath(current_path, netpath)) { + current_netpath = netpath; + } else { + current_netpath = current_path; + } + length = 2 + strlen(NOCATGETS("DMAKE_NPWD")) + strlen(current_netpath); + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("DMAKE_NPWD"), + current_netpath); + (void) putenv(env); + + /* Set DMAKE_UMASK to the value of umask */ + um = umask(0); + umask(um); + (void) sprintf(um_buf, NOCATGETS("%ul"), um); + length = 2 + strlen(NOCATGETS("DMAKE_UMASK")) + strlen(um_buf); + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("DMAKE_UMASK"), + um_buf); + (void) putenv(env); + + if (((prop = get_prop(shell_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + length = 2 + strlen(NOCATGETS("DMAKE_SHELL")) + + strlen(dmake_value->string_mb); + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("DMAKE_SHELL"), + dmake_value->string_mb); + (void) putenv(env); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + length = 2 + strlen(NOCATGETS("DMAKE_OUTPUT_MODE")) + + strlen(dmake_value->string_mb); + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("DMAKE_OUTPUT_MODE"), + dmake_value->string_mb); + (void) putenv(env); + } +} + +/* + * void + * distribute_rxm(Avo_DoJobMsg *dmake_job_msg) + * + * Write the DMake rule to be distributed down the pipe to rxm. + * + */ +void +distribute_rxm(Avo_DoJobMsg *dmake_job_msg) +{ + /* Add all dynamic env vars to the dmake_job_msg. */ + setvar_envvar(dmake_job_msg); + + /* + * Copying dosys()... + * Stat .make.state to see if we'll need to reread it later + */ + make_state->stat.time = file_no_time; + (void)exists(make_state); + make_state_before = make_state->stat.time; + + // Wait for the first Acknowledge message from the rxm process + // before sending the first message. + if (!firstAcknowledgeReceived) { + firstAcknowledgeReceived++; + Avo_AcknowledgeMsg *msg = getAcknowledgeMsg(); + if (msg) { + delete msg; + } + } + + RWCollectable *doJobMsg = (RWCollectable *)dmake_job_msg; + sigset_t newset; + sigset_t oldset; + + AVO_BLOCK_INTERUPTS; + int xdrResult = xdr(&xdrs_out, doJobMsg); + + if (xdrResult) { + fflush(dmake_ofp); + AVO_UNBLOCK_INTERUPTS; + } else { + AVO_UNBLOCK_INTERUPTS; + fatal(catgets(catd, 1, 249, "Couldn't send the job request to rxm")); + } + + delete dmake_job_msg; +} + +// Queue for JobResult messages. +static RWSlistCollectablesQueue jobResultQueue; + +// Queue for Acknowledge messages. +static RWSlistCollectablesQueue acknowledgeQueue; + +// Read a message from the rxm process, and put it into a queue, by +// message type. Return the message type. + +int +getRxmMessage(void) +{ + RWCollectable *msg = (RWCollectable *)0; + int msgType = 0; +// sigset_t newset; +// sigset_t oldset; + + // It seems unnecessarily to block interrupts here because + // any nonignored signal means exit for dmake in distributed mode. +// AVO_BLOCK_INTERUPTS; + int xdrResult = xdr(&xdrs_in, msg); +// AVO_UNBLOCK_INTERUPTS; + + if (xdrResult) { + switch(msg->isA()) { + case __AVO_ACKNOWLEDGEMSG: + acknowledgeQueue.append(msg); + msgType = __AVO_ACKNOWLEDGEMSG; + break; + case __AVO_JOBRESULTMSG: + jobResultQueue.append(msg); + msgType = __AVO_JOBRESULTMSG; + break; + default: + warning(catgets(catd, 1, 291, "Unknown message on rxm input fd")); + msgType = 0; + break; + } + } else { + if (errno == EINTR) { + fputs(NOCATGETS("dmake: Internal error: xdr() has been interrupted by a signal.\n"), stderr); + } + fatal(catgets(catd, 1, 250, "Couldn't receive message from rxm")); + } + + return msgType; +} + +// Get a JobResult message from it's queue, and +// if the queue is empty, call the getRxmMessage() function until +// a JobResult message shows. + +Avo_JobResultMsg * +getJobResultMsg(void) +{ + RWCollectable *msg = 0; + + if (!(msg = jobResultQueue.get())) { + while (getRxmMessage() != __AVO_JOBRESULTMSG); + msg = jobResultQueue.get(); + } + + return (Avo_JobResultMsg *)msg; +} + +// Get an Acknowledge message from it's queue, and +// if the queue is empty, call the getRxmMessage() function until +// a Acknowledge message shows. + +Avo_AcknowledgeMsg * +getAcknowledgeMsg(void) +{ + RWCollectable *msg = 0; + + if (!(msg = acknowledgeQueue.get())) { + while (getRxmMessage() != __AVO_ACKNOWLEDGEMSG); + msg = acknowledgeQueue.get(); + } + + return (Avo_AcknowledgeMsg *)msg; +} + + +/* + * Doname + * await_dist(Boolean waitflg) + * + * Waits for distributed children to exit and finishes their processing. + * Rxm will send a msg down the pipe when a child is done. + * + */ +Doname +await_dist(Boolean waitflg) +{ + Avo_JobResultMsg *dmake_result_msg; + int job_msg_id; + Doname result = build_ok; + int result_msg_cmd_status; + int result_msg_job_status; + Running rp; + + while (!(dmake_result_msg = getJobResultMsg())); + job_msg_id = dmake_result_msg->getId(); + result_msg_cmd_status = dmake_result_msg->getCmdStatus(); + result_msg_job_status = dmake_result_msg->getJobStatus(); + + if (waitflg) { + result = (result_msg_cmd_status == 0) ? build_ok : build_failed; + +#ifdef PRINT_EXIT_STATUS + if (result == build_ok) { + warning(NOCATGETS("I'm in await_dist(), waitflg is true, and result is build_ok.")); + } else { + warning(NOCATGETS("I'm in await_dist(), waitflg is true, and result is build_failed.")); + } +#endif + + } else { + for (rp = running_list; + (rp != NULL) && (job_msg_id != rp->job_msg_id); + rp = rp->next) { + } + if (rp == NULL) { + fatal(catgets(catd, 1, 251, "Internal error: returned child job_msg_id not in running_list")); + } else { + /* XXX - This may not be correct! */ + if (result_msg_job_status == RETURNED) { + rp->state = build_ok; + } else { + rp->state = (result_msg_cmd_status == 0) ? build_ok : build_failed; + } + result = rp->state; + +#ifdef PRINT_EXIT_STATUS + if (result == build_ok) { + warning(NOCATGETS("I'm in await_dist(), waitflg is false, and result is build_ok.")); + } else { + warning(NOCATGETS("I'm in await_dist(), waitflg is false, and result is build_failed.")); + } +#endif + + } + parallel_process_cnt--; + } + delete dmake_result_msg; + return result; +} + +#endif + + diff --git a/usr/src/make_src/Make/bin/make/common/dmake.cc b/usr/src/make_src/Make/bin/make/common/dmake.cc new file mode 100644 index 0000000..559a36d --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/dmake.cc @@ -0,0 +1,29 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)dmake.cc 1.2 06/12/12 + */ + +#pragma ident "@(#)dmake.cc 1.2 06/12/12" diff --git a/usr/src/make_src/Make/bin/make/common/doname.cc b/usr/src/make_src/Make/bin/make/common/doname.cc new file mode 100644 index 0000000..c06ba2f --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/doname.cc @@ -0,0 +1,3786 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)doname.cc 1.115 06/12/12 + */ + +#pragma ident "@(#)doname.cc 1.115 06/12/12" + +/* + * doname.c + * + * Figure out which targets are out of date and rebuild them + */ + +/* + * Included files + */ +#include <avo/avo_alloca.h> /* alloca() */ +#if defined(TEAMWARE_MAKE_CMN) +#include <avo/util.h> /* avo_get_user(), avo_hostname() */ +#endif + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +# include <avo/strings.h> /* AVO_STRDUP() */ +# include <dm/Avo_MToolJobResultMsg.h> +# include <dm/Avo_MToolJobStartMsg.h> +# include <dm/Avo_MToolRsrcInfoMsg.h> +# include <dm/Avo_macro_defs.h> /* AVO_BLOCK_INTERUPTS & AVO_UNBLOCK_INTERUPTS */ +# include <dmthread/Avo_ServerState.h> +# include <rw/pstream.h> +# include <rw/xdrstrea.h> +#endif + +#include <fcntl.h> +#include <mk/defs.h> +#include <mksh/i18n.h> /* get_char_semantics_value() */ +#include <mksh/macro.h> /* getvar(), expand_value() */ +#include <mksh/misc.h> /* getmem() */ +#include <poll.h> + +#ifdef PARALLEL +# include <rx/api.h> +#endif + +#include <signal.h> + +#ifndef HP_UX +# include <stropts.h> +#endif + +#include <sys/errno.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/utsname.h> /* uname() */ +#include <sys/wait.h> +#include <unistd.h> /* close() */ + +/* + * Defined macros + */ +#ifndef PARALLEL +# define LOCALHOST "localhost" +#endif + +#define MAXRULES 100 + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +#define SEND_MTOOL_MSG(cmds) \ + if (send_mtool_msgs) { \ + cmds \ + } +#else +#define SEND_MTOOL_MSG(cmds) +#endif + +// Sleep for .1 seconds between stat()'s +const int STAT_RETRY_SLEEP_TIME = 100000; + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +static char hostName[MAXNAMELEN] = ""; +static char userName[MAXNAMELEN] = ""; + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + static FILE *mtool_msgs_fp; + static XDR xdrs; + static int sent_rsrc_info_msg = 0; +#endif + +static int second_pass = 0; + +/* + * File table of contents + */ +extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic); +extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic); +static Boolean check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals); +void dynamic_dependencies(Name target); +static Doname run_command(register Property line, Boolean print_machine); +extern Doname execute_serial(Property line); +extern Name vpath_translation(register Name cmd); +extern void check_state(Name temp_file_name); +static void read_dependency_file(register Name filename); +static void check_read_state_file(void); +static void do_assign(register Name line, register Name target); +static void build_command_strings(Name target, register Property line); +static Doname touch_command(register Property line, register Name target, Doname result); +extern void update_target(Property line, Doname result); +static Doname sccs_get(register Name target, register Property *command); +extern void read_directory_of_file(register Name file); +static void add_pattern_conditionals(register Name target); +extern void set_locals(register Name target, register Property old_locals); +extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index); +extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics); +static void delete_query_chain(Chain ch); + +// From read2.cc +extern Name normalize_name(register wchar_t *name_string, register int length); + + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + static void append_job_result_msg(Avo_MToolJobResultMsg *job_result_msg); + static int pollResults(char *outFn, char *errFn, char *hostNm); + static void pollResultsAction(char *outFn, char *errFn); + static void rxmGetNextResultsBlock(int fd); + static int us_sleep(unsigned int nusecs); + extern "C" void Avo_PollResultsAction_Sigusr1Handler(int foo); +#endif + +/* + * DONE. + * + * doname_check(target, do_get, implicit, automatic) + * + * Will call doname() and then inspect the return value + * + * Return value: + * Indication if the build failed or not + * + * Parameters: + * target The target to build + * do_get Passed thru to doname() + * implicit Passed thru to doname() + * automatic Are we building a hidden dependency? + * + * Global variables used: + * build_failed_seen Set if -k is on and error occurs + * continue_after_error Indicates that -k is on + * report_dependencies No error msg if -P is on + */ +Doname +doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic) +{ + int first_time = 1; + (void) fflush(stdout); +try_again: + switch (doname(target, do_get, implicit, automatic)) { + case build_ok: + second_pass = 0; + return build_ok; + case build_running: + second_pass = 0; + return build_running; + case build_failed: + if (!continue_after_error) { + fatal(catgets(catd, 1, 13, "Target `%s' not remade because of errors"), + target->string_mb); + } + build_failed_seen = true; + second_pass = 0; + return build_failed; + case build_dont_know: + /* + * If we can't figure out how to build an automatic + * (hidden) dependency, we just ignore it. + * We later declare the target to be out of date just in + * case something changed. + * Also, don't complain if just reporting the dependencies + * and not building anything. + */ + if (automatic || (report_dependencies_level > 0)) { + second_pass = 0; + return build_dont_know; + } + if(first_time) { + first_time = 0; + second_pass = 1; + goto try_again; + } + second_pass = 0; + if (continue_after_error && !svr4) { + warning(catgets(catd, 1, 14, "Don't know how to make target `%s'"), + target->string_mb); + build_failed_seen = true; + return build_failed; + } + fatal(catgets(catd, 1, 15, "Don't know how to make target `%s'"), target->string_mb); + break; + } +#ifdef lint + return build_failed; +#endif +} + + +void +enter_explicit_rule_from_dynamic_rule(Name target, Name source) +{ + Property line, source_line; + Dependency dependency; + + source_line = get_prop(source->prop, line_prop); + line = maybe_append_prop(target, line_prop); + line->body.line.sccs_command = false; + line->body.line.target = target; + if (line->body.line.command_template == NULL) { + line->body.line.command_template = source_line->body.line.command_template; + for (dependency = source_line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + enter_dependency(line, dependency->name, false); + } + line->body.line.less = target; + } + line->body.line.percent = NULL; +} + + + +Name +find_dyntarget(Name target) +{ + Dyntarget p; + int i; + String_rec string; + wchar_t buffer[STRING_BUFFER_LENGTH]; + wchar_t *pp, * bufend; + wchar_t tbuffer[MAXPATHLEN]; + Wstring wcb(target); + + for (p = dyntarget_list; p != NULL; p = p->next) { + INIT_STRING_FROM_STACK(string, buffer); + expand_value(p->name, &string, false); + i = 0; + pp = string.buffer.start; + bufend = pp + STRING_BUFFER_LENGTH; + while((*pp != nul_char) && (pp < bufend)) { + if(iswspace(*pp)) { + tbuffer[i] = nul_char; + if(i > 0) { + if (wcb.equal(tbuffer)) { + enter_explicit_rule_from_dynamic_rule(target, p->name); + return(target); + } + } + pp++; + i = 0; + continue; + } + tbuffer[i] = *pp; + i++; + pp++; + if(*pp == nul_char) { + tbuffer[i] = nul_char; + if(i > 0) { + if (wcb.equal(tbuffer)) { + enter_explicit_rule_from_dynamic_rule(target, p->name); + return(target); + } + } + break; + } + } + } + return(NULL); +} + +/* + * DONE. + * + * doname(target, do_get, implicit) + * + * Chases all files the target depends on and builds any that + * are out of date. If the target is out of date it is then rebuilt. + * + * Return value: + * Indiates if build failed or nt + * + * Parameters: + * target Target to build + * do_get Run sccs get is nessecary + * implicit doname is trying to find an implicit rule + * + * Global variables used: + * assign_done True if command line assgnment has happened + * commands_done Preserved for the case that we need local value + * debug_level Should we trace make's actions? + * default_rule The rule for ".DEFAULT", used as last resort + * empty_name The Name "", used when looking for single sfx + * keep_state Indicates that .KEEP_STATE is on + * parallel True if building in parallel + * recursion_level Used for tracing + * report_dependencies make -P is on + */ +Doname +doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic) +{ + Doname result = build_dont_know; + Chain out_of_date_list = NULL; +#ifdef TEAMWARE_MAKE_CMN + Chain target_group; +#endif + Property old_locals = NULL; + register Property line; + Property command = NULL; + register Dependency dependency; + Name less = NULL; + Name true_target = target; + Name *automatics = NULL; + register int auto_count; + Boolean rechecking_target = false; + Boolean saved_commands_done; + Boolean restart = false; + Boolean save_parallel = parallel; +#ifdef NSE + Boolean save_readdep; +#endif + Boolean doing_subtree = false; + + Boolean recheck_conditionals = false; + + if (target->state == build_running) { + return build_running; + } + line = get_prop(target->prop, line_prop); +#ifdef TEAMWARE_MAKE_CMN + if (line != NULL) { + /* + * If this target is a member of target group and one of the + * other members of the group is running, mark this target + * as running. + */ + for (target_group = line->body.line.target_group; + target_group != NULL; + target_group = target_group->next) { + if (is_running(target_group->name)) { + target->state = build_running; + add_pending(target, + recursion_level, + do_get, + implicit, + false); + return build_running; + } + } + } +#ifdef NSE + nse_check_file_backquotes(target->string); +#endif +#endif + /* + * If the target is a constructed one for a "::" target, + * we need to consider that. + */ + if (target->has_target_prop) { + true_target = get_prop(target->prop, + target_prop)->body.target.target; + if (true_target->colon_splits > 0) { + /* Make sure we have a valid time for :: targets */ + Property time; + + time = get_prop(true_target->prop, time_prop); + if (time != NULL) { + true_target->stat.time = time->body.time.time; + } + } + } + (void) exists(true_target); + /* + * If the target has been processed, we don't need to do it again, + * unless it depends on conditional macros or a delayed assignment, + * or it has been done when KEEP_STATE is on. + */ + if (target->state == build_ok) { + if((!keep_state || (!target->depends_on_conditional && !assign_done))) { + return build_ok; + } else { + recheck_conditionals = true; + } + } + if (target->state == build_subtree) { + /* A dynamic macro subtree is being built */ + target->state = build_dont_know; + doing_subtree = true; + if (!target->checking_subtree) { + /* + * This target has been started before and therefore + * not all dependencies have to be built. + */ + restart = true; + } + } else if (target->state == build_pending) { + target->state = build_dont_know; + restart = true; +/* +#ifdef TEAMWARE_MAKE_CMN + } else if (parallel && + keep_state && + (target->conditional_cnt > 0)) { + if (!parallel_ok(target, false)) { + add_subtree(target, recursion_level, do_get, implicit); + target->state = build_running; + return build_running; + } +#endif + */ + } + /* + * If KEEP_STATE is on, we have to rebuild the target if the + * building of it caused new automatic dependencies to be reported. + * This is where we restart the build. + */ + if (line != NULL) { + line->body.line.percent = NULL; + } +recheck_target: + /* Init all local variables */ + result = build_dont_know; + out_of_date_list = NULL; + command = NULL; + less = NULL; + auto_count = 0; + if (!restart && line != NULL) { + /* + * If this target has never been built before, mark all + * of the dependencies as never built. + */ + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + dependency->built = false; + } + } + /* Save the set of automatic depes defined for this target */ + if (keep_state && + (line != NULL) && + (line->body.line.dependencies != NULL)) { + Name *p; + + /* + * First run thru the dependency list to see how many + * autos there are. + */ + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + if (dependency->automatic && !dependency->stale) { + auto_count++; + } + } + /* Create vector to hold the current autos */ + automatics = + (Name *) alloca((int) (auto_count * sizeof (Name))); + /* Copy them */ + for (p = automatics, dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + if (dependency->automatic && !dependency->stale) { + *p++ = dependency->name; + } + } + } + if (debug_level > 1) { + (void) printf(NOCATGETS("%*sdoname(%s)\n"), + recursion_level, + "", + target->string_mb); + } + recursion_level++; + /* Avoid infinite loops */ + if (target->state == build_in_progress) { + warning(catgets(catd, 1, 16, "Infinite loop: Target `%s' depends on itself"), + target->string_mb); + return build_ok; + } + target->state = build_in_progress; + + /* Activate conditional macros for the target */ + if (!target->added_pattern_conditionals) { + add_pattern_conditionals(target); + target->added_pattern_conditionals = true; + } + if (target->conditional_cnt > 0) { + old_locals = (Property) alloca(target->conditional_cnt * + sizeof (Property_rec)); + set_locals(target, old_locals); + } + +/* + * after making the call to dynamic_dependecies unconditional we can handle + * target names that are same as file name. In this case $$@ in the + * dependencies did not mean anything. WIth this change it expands it + * as expected. + */ + if (!target->has_depe_list_expanded) + { +#ifdef NSE + save_readdep = reading_dependencies; + reading_dependencies= true; +#endif + dynamic_dependencies(target); +#ifdef NSE + reading_dependencies= save_readdep; +#endif + } + +/* + * FIRST SECTION -- GO THROUGH DEPENDENCIES AND COLLECT EXPLICIT + * COMMANDS TO RUN + */ + if ((line = get_prop(target->prop, line_prop)) != NULL) { + if (check_dependencies(&result, + line, + do_get, + target, + true_target, + doing_subtree, + &out_of_date_list, + old_locals, + implicit, + &command, + less, + rechecking_target, + recheck_conditionals)) { + return build_running; + } + if (line->body.line.query != NULL) { + delete_query_chain(line->body.line.query); + } + line->body.line.query = out_of_date_list; + } + +#ifdef PARALLEL + if (doing_subtree) { + parallel = false; + } +#endif + +/* + * If the target is a :: type, do not try to find the rule for the target, + * all actions will be taken by separate branches. + * Else, we try to find an implicit rule using various methods, + * we quit as soon as one is found. + * + * [tolik, 12 Sep 2002] Do not try to find implicit rule for the target + * being rechecked - the target is being rechecked means that it already + * has explicit dependencies derived from an implicit rule found + * in previous step. + */ + if (target->colon_splits == 0 && !rechecking_target) { + /* Look for percent matched rule */ + if ((result == build_dont_know) && + (command == NULL)) { + switch (find_percent_rule( + target, + &command, + recheck_conditionals)) { + case build_failed: + result = build_failed; + break; +#ifdef TEAMWARE_MAKE_CMN + case build_running: + target->state = build_running; + add_pending(target, + --recursion_level, + do_get, + implicit, + false); + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return build_running; +#endif + case build_ok: + result = build_ok; + break; + } + } + /* Look for double suffix rule */ + if (result == build_dont_know) { + Property member; + + if (target->is_member && + ((member = get_prop(target->prop, member_prop)) != + NULL)) { + switch (find_ar_suffix_rule(target, + member->body. + member.member, + &command, + recheck_conditionals)) { + case build_failed: + result = build_failed; + break; +#ifdef TEAMWARE_MAKE_CMN + case build_running: + target->state = build_running; + add_pending(target, + --recursion_level, + do_get, + implicit, + false); + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return build_running; +#endif + default: + /* ALWAYS bind $% for old style */ + /* ar rules */ + if (line == NULL) { + line = + maybe_append_prop(target, + line_prop); + } + line->body.line.percent = + member->body.member.member; + break; + } + } else { + switch (find_double_suffix_rule(target, + &command, + recheck_conditionals)) { + case build_failed: + result = build_failed; + break; +#ifdef TEAMWARE_MAKE_CMN + case build_running: + target->state = build_running; + add_pending(target, + --recursion_level, + do_get, + implicit, + false); + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target-> + prop, + conditional_prop), + 0); + } + return build_running; +#endif + } + } + } + /* Look for single suffix rule */ + +/* /tolik/ + * I commented !implicit to fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules. + * This caused problem with SVR4 tilde rules (infinite recursion). So I made some changes in "implicit.cc" + */ +/* /tolik, 06.21.96/ + * Regression! See BugId 1255360 + * If more than one percent rules are defined for the same target then + * the behaviour of 'make' with my previous fix may be different from one + * of the 'old make'. + * The global variable second_pass (maybe it should be an argument to doname()) + * is intended to avoid this regression. It is set in doname_check(). + * First, 'make' will work as it worked before. Only when it is + * going to say "don't know how to make target" it sets second_pass to true and + * run 'doname' again but now trying to use Single Suffix Rules. + */ + if ((result == build_dont_know) && !automatic && (!implicit || second_pass) && + ((line == NULL) || + ((line->body.line.target != NULL) && + !line->body.line.target->has_regular_dependency))) { + switch (find_suffix_rule(target, + target, + empty_name, + &command, + recheck_conditionals)) { + case build_failed: + result = build_failed; + break; +#ifdef TEAMWARE_MAKE_CMN + case build_running: + target->state = build_running; + add_pending(target, + --recursion_level, + do_get, + implicit, + false); + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return build_running; +#endif + } + } + /* Try to sccs get */ + if ((command == NULL) && + (result == build_dont_know) && + do_get) { + result = sccs_get(target, &command); + } + + /* Use .DEFAULT rule if it is defined. */ + if ((command == NULL) && + (result == build_dont_know) && + (true_target->colons == no_colon) && + default_rule && + !implicit) { + /* Make sure we have a line prop */ + line = maybe_append_prop(target, line_prop); + command = line; + Boolean out_of_date; + if (true_target->is_member) { + out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time, + line->body.line.dependency_time); + } else { + out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time, + line->body.line.dependency_time); + } + if (build_unconditional || out_of_date) { + line->body.line.is_out_of_date = true; + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 17, "%*sBuilding %s using .DEFAULT because it is out of date\n"), + recursion_level, + "", + true_target->string_mb); + } + } + line->body.line.sccs_command = false; + line->body.line.command_template = default_rule; + line->body.line.target = true_target; + line->body.line.star = NULL; + line->body.line.less = true_target; + line->body.line.percent = NULL; + } + } + + /* We say "target up to date" if no cmd were executed for the target */ + if (!target->is_double_colon_parent) { + commands_done = false; + } + + silent = silent_all; + ignore_errors = ignore_errors_all; + if (posix) + { + if (!silent) + { + silent = (Boolean) target->silent_mode; + } + if (!ignore_errors) + { + ignore_errors = (Boolean) target->ignore_error_mode; + } + } + + int doname_dyntarget = 0; +r_command: + /* Run commands if any. */ + if ((command != NULL) && + (command->body.line.command_template != NULL)) { + if (result != build_failed) { + result = run_command(command, + (Boolean) ((parallel || save_parallel) && !silent)); +#ifdef NSE + nse_check_no_deps_no_rule(target, + get_prop(target->prop, line_prop), command); +#endif + } + switch (result) { +#ifdef TEAMWARE_MAKE_CMN + case build_running: + add_running(target, + true_target, + command, + --recursion_level, + auto_count, + automatics, + do_get, + implicit); + target->state = build_running; + if ((line = get_prop(target->prop, + line_prop)) != NULL) { + if (line->body.line.query != NULL) { + delete_query_chain(line->body.line.query); + } + line->body.line.query = NULL; + } + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return build_running; + case build_serial: + add_serial(target, + --recursion_level, + do_get, + implicit); + target->state = build_running; + line = get_prop(target->prop, line_prop); + if (line != NULL) { + if (line->body.line.query != NULL) { + delete_query_chain(line->body.line.query); + } + line->body.line.query = NULL; + } + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return build_running; +#endif + case build_ok: + /* If all went OK set a nice timestamp */ + if (true_target->stat.time == file_doesnt_exist) { + true_target->stat.time = file_max_time; + } + break; + } + } else { + /* + * If no command was found for the target, and it doesn't + * exist, and it is mentioned as a target in the makefile, + * we say it is extremely new and that it is OK. + */ + if (target->colons != no_colon) { + if (true_target->stat.time == file_doesnt_exist){ + true_target->stat.time = file_max_time; + } + result = build_ok; + } + /* + * Trying dynamic targets. + */ + if(!doname_dyntarget) { + doname_dyntarget = 1; + Name dtarg = find_dyntarget(target); + if(dtarg!=NULL) { + if (!target->has_depe_list_expanded) { + dynamic_dependencies(target); + } + if ((line = get_prop(target->prop, line_prop)) != NULL) { + if (check_dependencies(&result, + line, + do_get, + target, + true_target, + doing_subtree, + &out_of_date_list, + old_locals, + implicit, + &command, + less, + rechecking_target, + recheck_conditionals)) + { + return build_running; + } + if (line->body.line.query != NULL) { + delete_query_chain(line->body.line.query); + } + line->body.line.query = out_of_date_list; + } + goto r_command; + } + } + /* + * If the file exists, it is OK that we couldnt figure + * out how to build it. + */ + (void) exists(target); + if ((target->stat.time != file_doesnt_exist) && + (result == build_dont_know)) { + result = build_ok; + } + } + + /* + * Some of the following is duplicated in the function finish_doname. + * If anything is changed here, check to see if it needs to be + * changed there. + */ + if ((line = get_prop(target->prop, line_prop)) != NULL) { + if (line->body.line.query != NULL) { + delete_query_chain(line->body.line.query); + } + line->body.line.query = NULL; + } + target->state = result; + parallel = save_parallel; + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, conditional_prop), + 0); + } + recursion_level--; + if (target->is_member) { + Property member; + + /* Propagate the timestamp from the member file to the member*/ + if ((target->stat.time != file_max_time) && + ((member = get_prop(target->prop, member_prop)) != NULL) && + (exists(member->body.member.member) > file_doesnt_exist)) { + target->stat.time = + member->body.member.member->stat.time; + } + } + /* + * Check if we found any new auto dependencies when we + * built the target. + */ + if ((result == build_ok) && check_auto_dependencies(target, + auto_count, + automatics)) { + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 18, "%*sTarget `%s' acquired new dependencies from build, rechecking all dependencies\n"), + recursion_level, + "", + true_target->string_mb); + } + rechecking_target = true; + saved_commands_done = commands_done; + goto recheck_target; + } + + if (rechecking_target && !commands_done) { + commands_done = saved_commands_done; + } + + return result; +} + +/* + * DONE. + * + * check_dependencies(result, line, do_get, + * target, true_target, doing_subtree, out_of_date_tail, + * old_locals, implicit, command, less, rechecking_target) + * + * Return value: + * True returned if some dependencies left running + * + * Parameters: + * result Pointer to cell we update if build failed + * line We get the dependencies from here + * do_get Allow use of sccs get in recursive doname() + * target The target to chase dependencies for + * true_target The real one for :: and lib(member) + * doing_subtree True if building a conditional macro subtree + * out_of_date_tail Used to set the $? list + * old_locals Used for resetting the local macros + * implicit Called when scanning for implicit rules? + * command Place to stuff command + * less Set to $< value + * + * Global variables used: + * command_changed Set if we suspect .make.state needs rewrite + * debug_level Should we trace actions? + * force The Name " FORCE", compared against + * recursion_level Used for tracing + * rewrite_statefile Set if .make.state needs rewriting + * wait_name The Name ".WAIT", compared against + */ +static Boolean +#ifdef TEAMWARE_MAKE_CMN +check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean doing_subtree, Chain *out_of_date_tail, Property old_locals, Boolean implicit, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals) +#else +check_dependencies(Doname *result, Property line, Boolean do_get, Name target, Name true_target, Boolean, Chain *out_of_date_tail, Property, Boolean, Property *command, Name less, Boolean rechecking_target, Boolean recheck_conditionals) +#endif +{ + Boolean dependencies_running; + register Dependency dependency; + Doname dep_result; + Boolean dependency_changed = false; + + line->body.line.dependency_time = file_doesnt_exist; + if (line->body.line.query != NULL) { + delete_query_chain(line->body.line.query); + } + line->body.line.query = NULL; + line->body.line.is_out_of_date = false; + dependencies_running = false; + /* + * Run thru all the dependencies and call doname() recursively + * on each of them. + */ + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + Boolean this_dependency_changed = false; + + if (!dependency->automatic && + (rechecking_target || target->rechecking_target)) { + /* + * We only bother with the autos when rechecking + */ + continue; + } + + if (dependency->name == wait_name) { + /* + * The special target .WAIT means finish all of + * the prior dependencies before continuing. + */ + if (dependencies_running) { + break; + } +#ifdef DISTRIBUTED + } else if ((!parallel_ok(dependency->name, false)) && + (dependencies_running)) { + /* + * If we can't execute the current dependency in + * parallel, hold off the dependency processing + * to preserve the order of the dependencies. + */ + break; +#endif + } else { + timestruc_t depe_time = file_doesnt_exist; + + + if (true_target->is_member) { + depe_time = exists(dependency->name); + } + if (dependency->built || + (dependency->name->state == build_failed)) { + dep_result = (Doname) dependency->name->state; + } else { +#ifdef NSE + nse_check_sccs(target->string, + dependency->name->string); + nse_check_derived_src(target, + dependency->name->string, + line->body.line.command_template); +#endif + dep_result = doname_check(dependency->name, + do_get, + false, + (Boolean) dependency->automatic); + } + if (true_target->is_member || dependency->name->is_member) { + /* should compare only secs, cause lib members does not have nsec time resolution */ + if (depe_time.tv_sec != dependency->name->stat.time.tv_sec) { + this_dependency_changed = + dependency_changed = + true; + } + } else { + if (depe_time != dependency->name->stat.time) { + this_dependency_changed = + dependency_changed = + true; + } + } + dependency->built = true; + switch (dep_result) { + case build_running: + dependencies_running = true; + continue; + case build_failed: + *result = build_failed; + break; + case build_dont_know: +/* + * If make can't figure out how to make a dependency, maybe the dependency + * is out of date. In this case, we just declare the target out of date + * and go on. If we really need the dependency, the make'ing of the target + * will fail. This will only happen for automatic (hidden) dependencies. + */ + if(!recheck_conditionals) { + line->body.line.is_out_of_date = true; + } + /* + * Make sure the dependency is not saved + * in the state file. + */ + dependency->stale = true; + rewrite_statefile = + command_changed = + true; + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 19, "Target %s rebuilt because dependency %s does not exist\n"), + true_target->string_mb, + dependency->name->string_mb); + } + break; + } + if (dependency->name->depends_on_conditional) { + target->depends_on_conditional = true; + } + if (dependency->name == force) { + target->stat.time = + dependency->name->stat.time; + } + /* + * Propagate new timestamp from "member" to + * "lib.a(member)". + */ + (void) exists(dependency->name); + + /* Collect the timestamp of the youngest dependency */ + line->body.line.dependency_time = + MAX(dependency->name->stat.time, + line->body.line.dependency_time); + + /* Correction: do not consider nanosecs for members */ + if(true_target->is_member || dependency->name->is_member) { + line->body.line.dependency_time.tv_nsec = 0; + } + + if (debug_level > 1) { + (void) printf(catgets(catd, 1, 20, "%*sDate(%s)=%s \n"), + recursion_level, + "", + dependency->name->string_mb, + time_to_string(dependency->name-> + stat.time)); + if (dependency->name->stat.time > line->body.line.dependency_time) { + (void) printf(catgets(catd, 1, 21, "%*sDate-dependencies(%s) set to %s\n"), + recursion_level, + "", + true_target->string_mb, + time_to_string(line->body.line. + dependency_time)); + } + } + + /* Build the $? list */ + if (true_target->is_member) { + if (this_dependency_changed == true) { + true_target->stat.time = dependency->name->stat.time; + true_target->stat.time.tv_sec--; + } else { + /* Dina: + * The next statement is commented + * out as a fix for bug #1051032. + * if dependency hasn't changed + * then there's no need to invalidate + * true_target. This statemnt causes + * make to take much longer to process + * an already-built archive. Soren + * said it was a quick fix for some + * problem he doesn't remember. + true_target->stat.time = file_no_time; + */ + (void) exists(true_target); + } + } else { + (void) exists(true_target); + } + Boolean out_of_date; + if (true_target->is_member || dependency->name->is_member) { + out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time, + dependency->name->stat.time); + } else { + out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time, + dependency->name->stat.time); + } + if ((build_unconditional || out_of_date) && + (dependency->name != force) && + (dependency->stale == false)) { + *out_of_date_tail = ALLOC(Chain); + if (dependency->name->is_member && + (get_prop(dependency->name->prop, + member_prop) != NULL)) { + (*out_of_date_tail)->name = + get_prop(dependency->name->prop, + member_prop)-> + body.member.member; + } else { + (*out_of_date_tail)->name = + dependency->name; + } + (*out_of_date_tail)->next = NULL; + out_of_date_tail = &(*out_of_date_tail)->next; + if (debug_level > 0) { + if (dependency->name->stat.time == file_max_time) { + (void) printf(catgets(catd, 1, 22, "%*sBuilding %s because %s does not exist\n"), + recursion_level, + "", + true_target->string_mb, + dependency->name->string_mb); + } else { + (void) printf(catgets(catd, 1, 23, "%*sBuilding %s because it is out of date relative to %s\n"), + recursion_level, + "", + true_target->string_mb, + dependency->name->string_mb); + } + } + } + if (dependency->name == force) { + force->stat.time = + file_max_time; + force->state = build_dont_know; + } + } + } +#ifdef TEAMWARE_MAKE_CMN + if (dependencies_running) { + if (doing_subtree) { + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return true; + } else { + target->state = build_running; + add_pending(target, + --recursion_level, + do_get, + implicit, + false); + if (target->conditional_cnt > 0) { + reset_locals(target, + old_locals, + get_prop(target->prop, + conditional_prop), + 0); + } + return true; + } + } +#endif + /* + * Collect the timestamp of the youngest double colon target + * dependency. + */ + if (target->is_double_colon_parent) { + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + Property tmp_line; + + if ((tmp_line = get_prop(dependency->name->prop, line_prop)) != NULL) { + if(tmp_line->body.line.dependency_time != file_max_time) { + target->stat.time = + MAX(tmp_line->body.line.dependency_time, + target->stat.time); + } + } + } + } + if ((true_target->is_member) && (dependency_changed == true)) { + true_target->stat.time = file_no_time; + } + /* + * After scanning all the dependencies, we check the rule + * if we found one. + */ + if (line->body.line.command_template != NULL) { + if (line->body.line.command_template_redefined) { + warning(catgets(catd, 1, 24, "Too many rules defined for target %s"), + target->string_mb); + } + *command = line; + /* Check if the target is out of date */ + Boolean out_of_date; + if (true_target->is_member) { + out_of_date = (Boolean) OUT_OF_DATE_SEC(true_target->stat.time, + line->body.line.dependency_time); + } else { + out_of_date = (Boolean) OUT_OF_DATE(true_target->stat.time, + line->body.line.dependency_time); + } + if (build_unconditional || out_of_date){ + if(!recheck_conditionals) { + line->body.line.is_out_of_date = true; + } + } + line->body.line.sccs_command = false; + line->body.line.target = true_target; + if(gnu_style) { + + // set $< for explicit rule + if(line->body.line.dependencies != NULL) { + less = line->body.line.dependencies->name; + } + + // set $* for explicit rule + Name target_body; + Name tt = true_target; + Property member; + register wchar_t *target_end; + register Dependency suffix; + register int suffix_length; + Wstring targ_string; + Wstring suf_string; + + if (true_target->is_member && + ((member = get_prop(target->prop, member_prop)) != + NULL)) { + tt = member->body.member.member; + } + targ_string.init(tt); + target_end = targ_string.get_string() + tt->hash.length; + for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { + suffix_length = suffix->name->hash.length; + suf_string.init(suffix->name); + if (tt->hash.length < suffix_length) { + continue; + } else if (!IS_WEQUALN(suf_string.get_string(), + (target_end - suffix_length), + suffix_length)) { + continue; + } + target_body = GETNAME( + targ_string.get_string(), + (int)(tt->hash.length - suffix_length) + ); + line->body.line.star = target_body; + } + + // set result = build_ok so that implicit rules are not used. + if(*result == build_dont_know) { + *result = build_ok; + } + } + if (less != NULL) { + line->body.line.less = less; + } + } + + return false; +} + +/* + * dynamic_dependencies(target) + * + * Checks if any dependency contains a macro ref + * If so, it replaces the dependency with the expanded version. + * Here, "$@" gets translated to target->string. That is + * the current name on the left of the colon in the + * makefile. Thus, + * xyz: s.$@.c + * translates into + * xyz: s.xyz.c + * + * Also, "$(@F)" translates to the same thing without a preceeding + * directory path (if one exists). + * Note, to enter "$@" on a dependency line in a makefile + * "$$@" must be typed. This is because make expands + * macros in dependency lists upon reading them. + * dynamic_dependencies() also expands file wildcards. + * If there are any Shell meta characters in the name, + * search the directory, and replace the dependency + * with the set of files the pattern matches + * + * Parameters: + * target Target to sanitize dependencies for + * + * Global variables used: + * c_at The Name "@", used to set macro value + * debug_level Should we trace actions? + * dot The Name ".", used to read directory + * recursion_level Used for tracing + */ +void +dynamic_dependencies(Name target) +{ + wchar_t pattern[MAXPATHLEN]; + register wchar_t *p; + Property line; + register Dependency dependency; + register Dependency *remove; + String_rec string; + wchar_t buffer[MAXPATHLEN]; + register Boolean set_at = false; + register wchar_t *start; + Dependency new_depe; + register Boolean reuse_cell; + Dependency first_member; + Name directory; + Name lib; + Name member; + Property prop; + Name true_target = target; + wchar_t *library; + + if ((line = get_prop(target->prop, line_prop)) == NULL) { + return; + } + /* If the target is constructed from a "::" target we consider that */ + if (target->has_target_prop) { + true_target = get_prop(target->prop, + target_prop)->body.target.target; + } + /* Scan all dependencies and process the ones that contain "$" chars */ + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + if (!dependency->name->dollar) { + continue; + } + target->has_depe_list_expanded = true; + + /* The make macro $@ is bound to the target name once per */ + /* invocation of dynamic_dependencies() */ + if (!set_at) { + (void) SETVAR(c_at, true_target, false); + set_at = true; + } + /* Expand this dependency string */ + INIT_STRING_FROM_STACK(string, buffer); + expand_value(dependency->name, &string, false); + /* Scan the expanded string. It could contain whitespace */ + /* which mean it expands to several dependencies */ + start = string.buffer.start; + while (iswspace(*start)) { + start++; + } + /* Remove the cell (later) if the macro was empty */ + if (start[0] == (int) nul_char) { + dependency->name = NULL; + } + +/* azv 10/26/95 to fix bug BID_1170218 */ + if ((start[0] == (int) period_char) && + (start[1] == (int) slash_char)) { + start += 2; + } +/* azv */ + + first_member = NULL; + /* We use the original dependency cell for the first */ + /* dependency from the expansion */ + reuse_cell = true; + /* We also have to deal with dependencies that expand to */ + /* lib.a(members) notation */ + for (p = start; *p != (int) nul_char; p++) { + if ((*p == (int) parenleft_char)) { + lib = GETNAME(start, p - start); + lib->is_member = true; + first_member = dependency; + start = p + 1; + while (iswspace(*start)) { + start++; + } + break; + } + } + do { + /* First skip whitespace */ + for (p = start; *p != (int) nul_char; p++) { + if ((*p == (int) nul_char) || + iswspace(*p) || + (*p == (int) parenright_char)) { + break; + } + } + /* Enter dependency from expansion */ + if (p != start) { + /* Create new dependency cell if */ + /* this is not the first dependency */ + /* picked from the expansion */ + if (!reuse_cell) { + new_depe = ALLOC(Dependency); + new_depe->next = dependency->next; + new_depe->automatic = false; + new_depe->stale = false; + new_depe->built = false; + dependency->next = new_depe; + dependency = new_depe; + } + reuse_cell = false; + /* Internalize the dependency name */ + // tolik. Fix for bug 4110429: inconsistent expansion for macros that + // include "//" and "/./" + //dependency->name = GETNAME(start, p - start); + dependency->name = normalize_name(start, p - start); + if ((debug_level > 0) && + (first_member == NULL)) { + (void) printf(catgets(catd, 1, 25, "%*sDynamic dependency `%s' for target `%s'\n"), + recursion_level, + "", + dependency->name->string_mb, + true_target->string_mb); + } + for (start = p; iswspace(*start); start++); + p = start; + } + } while ((*p != (int) nul_char) && + (*p != (int) parenright_char)); + /* If the expansion was of lib.a(members) format we now */ + /* enter the proper member cells */ + if (first_member != NULL) { + /* Scan the new dependencies and transform them from */ + /* "foo" to "lib.a(foo)" */ + for (; 1; first_member = first_member->next) { + /* Build "lib.a(foo)" name */ + INIT_STRING_FROM_STACK(string, buffer); + APPEND_NAME(lib, + &string, + (int) lib->hash.length); + append_char((int) parenleft_char, &string); + APPEND_NAME(first_member->name, + &string, + FIND_LENGTH); + append_char((int) parenright_char, &string); + member = first_member->name; + /* Replace "foo" with "lib.a(foo)" */ + first_member->name = + GETNAME(string.buffer.start, FIND_LENGTH); + if (string.free_after_use) { + retmem(string.buffer.start); + } + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 26, "%*sDynamic dependency `%s' for target `%s'\n"), + recursion_level, + "", + first_member->name-> + string_mb, + true_target->string_mb); + } + first_member->name->is_member = lib->is_member; + /* Add member property to member */ + prop = maybe_append_prop(first_member->name, + member_prop); + prop->body.member.library = lib; + prop->body.member.entry = NULL; + prop->body.member.member = member; + if (first_member == dependency) { + break; + } + } + } + } + Wstring wcb; + /* Then scan all the dependencies again. This time we want to expand */ + /* shell file wildcards */ + for (remove = &line->body.line.dependencies, dependency = *remove; + dependency != NULL; + dependency = *remove) { + if (dependency->name == NULL) { + dependency = *remove = (*remove)->next; + continue; + } + /* If dependency name string contains shell wildcards */ + /* replace the name with the expansion */ + if (dependency->name->wildcard) { +#ifdef NSE + nse_wildcard(target->string, dependency->name->string); +#endif + wcb.init(dependency->name); + if ((start = (wchar_t *) wschr(wcb.get_string(), + (int) parenleft_char)) != NULL) { + /* lib(*) type pattern */ + library = buffer; + (void) wsncpy(buffer, + wcb.get_string(), + start - wcb.get_string()); + buffer[start-wcb.get_string()] = + (int) nul_char; + (void) wsncpy(pattern, + start + 1, +(int) (dependency->name->hash.length-(start-wcb.get_string())-2)); + pattern[dependency->name->hash.length - + (start-wcb.get_string()) - 2] = + (int) nul_char; + } else { + library = NULL; + (void) wsncpy(pattern, + wcb.get_string(), + (int) dependency->name->hash.length); + pattern[dependency->name->hash.length] = + (int) nul_char; + } + start = (wchar_t *) wsrchr(pattern, (int) slash_char); + if (start == NULL) { + directory = dot; + p = pattern; + } else { + directory = GETNAME(pattern, start-pattern); + p = start+1; + } + /* The expansion is handled by the read_dir() routine*/ + if (read_dir(directory, p, line, library)) { + *remove = (*remove)->next; + } else { + remove = &dependency->next; + } + } else { + remove = &dependency->next; + } + } + + /* Then unbind $@ */ + (void) SETVAR(c_at, (Name) NULL, false); +} + +/* + * DONE. + * + * run_command(line) + * + * Takes one Cmd_line and runs the commands from it. + * + * Return value: + * Indicates if the command failed or not + * + * Parameters: + * line The command line to run + * + * Global variables used: + * commands_done Set if we do run command + * current_line Set to the line we run a command from + * current_target Set to the target we run a command for + * file_number Used to form temp file name + * keep_state Indicates that .KEEP_STATE is on + * make_state The Name ".make.state", used to check timestamp + * parallel True if currently building in parallel + * parallel_process_cnt Count of parallel processes running + * quest Indicates that make -q is on + * rewrite_statefile Set if we do run a command + * sunpro_dependencies The Name "SUNPRO_DEPENDENCIES", set value + * temp_file_directory Used to form temp fie name + * temp_file_name Set to the name of the temp file + * touch Indicates that make -t is on + */ +static Doname +run_command(register Property line, Boolean) +{ + register Doname result = build_ok; + register Boolean remember_only = false; + register Name target = line->body.line.target; + wchar_t *string; + char tmp_file_path[MAXPATHLEN]; + + if (!line->body.line.is_out_of_date && target->rechecking_target) { + target->rechecking_target = false; + return build_ok; + } + + /* + * Build the command if we know the target is out of date, + * or if we want to check cmd consistency. + */ + if (line->body.line.is_out_of_date || keep_state) { + /* Hack for handling conditional macros in DMake. */ + if (!line->body.line.dont_rebuild_command_used) { + build_command_strings(target, line); + } + } + /* Never mind */ + if (!line->body.line.is_out_of_date) { + return build_ok; + } + /* If quest, then exit(1) because the target is out of date */ + if (quest) { + if (posix) { +#ifdef TEAMWARE_MAKE_CMN + result = execute_parallel(line, true); +#else + result = execute_serial(line); +#endif + } +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + exit_status = 1; +#endif + exit(1); + } + /* We actually had to do something this time */ + rewrite_statefile = commands_done = true; + /* + * If this is an sccs command, we have to do some extra checking + * and possibly complain. If the file can't be gotten because it's + * checked out, we complain and behave as if the command was + * executed eventhough we ignored the command. + */ + if (!touch && + line->body.line.sccs_command && + (target->stat.time != file_doesnt_exist) && + ((target->stat.mode & 0222) != 0)) { + fatal(catgets(catd, 1, 27, "%s is writable so it cannot be sccs gotten"), + target->string_mb); + target->has_complained = remember_only = true; + } + /* + * If KEEP_STATE is on, we make sure we have the timestamp for + * .make.state. If .make.state changes during the command run, + * we reread .make.state after the command. We also setup the + * environment variable that asks utilities to report dependencies. + */ + if (!touch && + keep_state && + !remember_only) { + (void) exists(make_state); + if((strlen(temp_file_directory) == 1) && + (temp_file_directory[0] == '/')) { + tmp_file_path[0] = '\0'; + } else { + strcpy(tmp_file_path, temp_file_directory); + } + sprintf(mbs_buffer, + NOCATGETS("%s/.make.dependency.%08x.%d.%d"), + tmp_file_path, + hostid, + getpid(), + file_number++); + MBSTOWCS(wcs_buffer, mbs_buffer); + Boolean fnd; + temp_file_name = getname_fn(wcs_buffer, FIND_LENGTH, false, &fnd); + temp_file_name->stat.is_file = true; + int len = 2*MAXPATHLEN + strlen(target->string_mb) + 2; + wchar_t *to = string = ALLOC_WC(len); + for (wchar_t *from = wcs_buffer; *from != (int) nul_char; ) { + if (*from == (int) space_char) { + *to++ = (int) backslash_char; + } + *to++ = *from++; + } + *to++ = (int) space_char; + MBSTOWCS(to, target->string_mb); + Name sprodep_name = getname_fn(string, FIND_LENGTH, false, &fnd); + (void) SETVAR(sunpro_dependencies, + sprodep_name, + false); + retmem(string); + } else { + temp_file_name = NULL; + } + + /* + * In case we are interrupted, we need to know what was going on. + */ + current_target = target; + /* + * We also need to be able to save an empty command instead of the + * interrupted one in .make.state. + */ + current_line = line; + if (remember_only) { + /* Empty block!!! */ + } else if (touch) { + result = touch_command(line, target, result); + if (posix) { +#ifdef TEAMWARE_MAKE_CMN + result = execute_parallel(line, true); +#else + result = execute_serial(line); +#endif + } + } else { + /* + * If this is not a touch run, we need to execute the + * proper command(s) for the target. + */ +#ifdef TEAMWARE_MAKE_CMN + if (parallel) { + if (!parallel_ok(target, true)) { + /* + * We are building in parallel, but + * this target must be built in serial. + */ + /* + * If nothing else is building, + * do this one, else wait. + */ + if (parallel_process_cnt == 0) { +#ifdef TEAMWARE_MAKE_CMN + result = execute_parallel(line, true, target->localhost); +#else + result = execute_serial(line); +#endif + } else { + current_target = NULL; + current_line = NULL; +/* + line->body.line.command_used = NULL; + */ + line->body.line.dont_rebuild_command_used = true; + return build_serial; + } + } else { + result = execute_parallel(line, false); + switch (result) { + case build_running: + return build_running; + case build_serial: + if (parallel_process_cnt == 0) { +#ifdef TEAMWARE_MAKE_CMN + result = execute_parallel(line, true, target->localhost); +#else + result = execute_serial(line); +#endif + } else { + current_target = NULL; + current_line = NULL; + target->parallel = false; + line->body.line.command_used = + NULL; + return build_serial; + } + } + } + } else { +#endif +#ifdef TEAMWARE_MAKE_CMN + result = execute_parallel(line, true, target->localhost); +#else + result = execute_serial(line); +#endif +#ifdef TEAMWARE_MAKE_CMN + } +#endif + } + temp_file_name = NULL; + if (report_dependencies_level == 0){ + update_target(line, result); + } + current_target = NULL; + current_line = NULL; + return result; +} + +/* + * execute_serial(line) + * + * Runs thru the command line for the target and + * executes the rules one by one. + * + * Return value: + * The result of the command build + * + * Parameters: + * line The command to execute + * + * Static variables used: + * + * Global variables used: + * continue_after_error -k flag + * do_not_exec_rule -n flag + * report_dependencies -P flag + * silent Don't echo commands before executing + * temp_file_name Temp file for auto dependencies + * vpath_defined If true, translate path for command + */ +Doname +execute_serial(Property line) +{ + int child_pid = 0; +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + Avo_MToolJobResultMsg *job_result_msg; + RWCollectable *xdr_msg; +#endif + Boolean printed_serial; + Doname result = build_ok; + Cmd_line rule, cmd_tail, command = NULL; + char mbstring[MAXPATHLEN]; + int filed; + Name target = line->body.line.target; + + SEND_MTOOL_MSG( + if (!sent_rsrc_info_msg) { + if (userName[0] == '\0') { + avo_get_user(userName, NULL); + } + if (hostName[0] == '\0') { + strcpy(hostName, avo_hostname()); + } + send_rsrc_info_msg(1, hostName, userName); + sent_rsrc_info_msg = 1; + } + send_job_start_msg(line); + job_result_msg = new Avo_MToolJobResultMsg(); + ); + + target->has_recursive_dependency = false; + // We have to create a copy of the rules chain for processing because + // the original one can be destroyed during .make.state file rereading. + for (rule = line->body.line.command_used; + rule != NULL; + rule = rule->next) { + if (command == NULL) { + command = cmd_tail = ALLOC(Cmd_line); + } else { + cmd_tail->next = ALLOC(Cmd_line); + cmd_tail = cmd_tail->next; + } + *cmd_tail = *rule; + } + if (command) { + cmd_tail->next = NULL; + } + for (rule = command; rule != NULL; rule = rule->next) { + if (posix && (touch || quest) && !rule->always_exec) { + continue; + } + if (vpath_defined) { + rule->command_line = + vpath_translation(rule->command_line); + } + /* Echo command line, maybe. */ + if ((rule->command_line->hash.length > 0) && + !silent && + (!rule->silent || do_not_exec_rule) && + (report_dependencies_level == 0)) { + (void) printf("%s\n", rule->command_line->string_mb); + SEND_MTOOL_MSG( + job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb)); + ); + } + if (rule->command_line->hash.length > 0) { + SEND_MTOOL_MSG( + (void) sprintf(mbstring, + NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"), + tmpdir, + getpid(), + file_number++); + + int tmp_fd = mkstemp(mbstring); + if(tmp_fd) { + (void) close(tmp_fd); + } + + stdout_file = strdup(mbstring); + stderr_file = NULL; + child_pid = pollResults(stdout_file, + (char *)NULL, + (char *)NULL); + ); + /* Do assignment if command line prefixed with "=" */ + if (rule->assign) { + result = build_ok; + do_assign(rule->command_line, target); + } else if (report_dependencies_level == 0) { + /* Execute command line. */ +#ifdef DISTRIBUTED + setvar_envvar((Avo_DoJobMsg *)NULL); +#else + setvar_envvar(); +#endif + result = dosys(rule->command_line, + (Boolean) rule->ignore_error, + (Boolean) rule->make_refd, + /* ds 98.04.23 bug #4085164. make should always show error messages */ + false, + /* BOOLEAN(rule->silent && + rule->ignore_error), */ + (Boolean) rule->always_exec, + target, + send_mtool_msgs); +#ifdef NSE + nse_did_recursion= false; +#endif + check_state(temp_file_name); +#ifdef NSE + nse_check_cd(line); +#endif + } + SEND_MTOOL_MSG( + append_job_result_msg(job_result_msg); + if (child_pid > 0) { + kill(child_pid, SIGUSR1); + while (!((waitpid(child_pid, 0, 0) == -1) + && (errno == ECHILD))); + } + child_pid = 0; + (void) unlink(stdout_file); + retmem_mb(stdout_file); + stdout_file = NULL; + ); + } else { + result = build_ok; + } + if (result == build_failed) { + if (silent || rule->silent) { + (void) printf(catgets(catd, 1, 242, "The following command caused the error:\n%s\n"), + rule->command_line->string_mb); + SEND_MTOOL_MSG( + job_result_msg->appendOutput(AVO_STRDUP(catgets(catd, 1, 243, "The following command caused the error:"))); + job_result_msg->appendOutput(AVO_STRDUP(rule->command_line->string_mb)); + ); + } + if (!rule->ignore_error && !ignore_errors) { + if (!continue_after_error) { + SEND_MTOOL_MSG( + job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE); + xdr_msg = (RWCollectable*) + job_result_msg; + xdr(&xdrs, xdr_msg); + (void) fflush(mtool_msgs_fp); + delete job_result_msg; + ); + fatal(catgets(catd, 1, 244, "Command failed for target `%s'"), + target->string_mb); + } + /* + * Make sure a failing command is not + * saved in .make.state. + */ + line->body.line.command_used = NULL; + break; + } else { + result = build_ok; + } + } + } + for (rule = command; rule != NULL; rule = cmd_tail) { + cmd_tail = rule->next; + free(rule); + } + command = NULL; + SEND_MTOOL_MSG( + job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE); + xdr_msg = (RWCollectable*) job_result_msg; + xdr(&xdrs, xdr_msg); + (void) fflush(mtool_msgs_fp); + + delete job_result_msg; + ); + if (temp_file_name != NULL) { + free_name(temp_file_name); + } + temp_file_name = NULL; + + Property spro = get_prop(sunpro_dependencies->prop, macro_prop); + if(spro != NULL) { + Name val = spro->body.macro.value; + if(val != NULL) { + free_name(val); + spro->body.macro.value = NULL; + } + } + spro = get_prop(sunpro_dependencies->prop, env_mem_prop); + if(spro) { + char *val = spro->body.env_mem.value; + if(val != NULL) { + /* + * Do not return memory allocated for SUNPRO_DEPENDENCIES + * It will be returned in setvar_daemon() in macro.cc + */ + // retmem_mb(val); + spro->body.env_mem.value = NULL; + } + } + + return result; +} + + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + +/* + * Create and send an Avo_MToolRsrcInfoMsg. + */ +void +send_rsrc_info_msg(int max_jobs, char *hostname, char *username) +{ + static int first = 1; + Avo_MToolRsrcInfoMsg *msg; + RWSlistCollectables server_list; + Avo_ServerState *server_state; + RWCollectable *xdr_msg; + + if (!first) { + return; + } + first = 0; + + create_xdrs_ptr(); + + server_state = new Avo_ServerState(max_jobs, hostname, username); + server_list.append(server_state); + msg = new Avo_MToolRsrcInfoMsg(&server_list); + + xdr_msg = (RWCollectable *)msg; + xdr(get_xdrs_ptr(), xdr_msg); + (void) fflush(get_mtool_msgs_fp()); + + delete server_state; + delete msg; +} + +/* + * Create and send an Avo_MToolJobStartMsg. + */ +void +send_job_start_msg(Property line) +{ + int cmd_options = 0; + Avo_MToolJobStartMsg *msg; + Cmd_line rule; + Name target = line->body.line.target; + RWCollectable *xdr_msg; + + if (userName[0] == '\0') { + avo_get_user(userName, NULL); + } + if (hostName[0] == '\0') { + strcpy(hostName, avo_hostname()); + } + + msg = new Avo_MToolJobStartMsg(); + msg->setJobId(++job_msg_id); + msg->setTarget(AVO_STRDUP(target->string_mb)); + msg->setHost(AVO_STRDUP(hostName)); + msg->setUser(AVO_STRDUP(userName)); + + for (rule = line->body.line.command_used; + rule != NULL; + rule = rule->next) { + if (posix && (touch || quest) && !rule->always_exec) { + continue; + } + if (vpath_defined) { + rule->command_line = + vpath_translation(rule->command_line); + } + cmd_options = 0; + if (rule->ignore_error || ignore_errors) { + cmd_options |= ignore_mask; + } + if (rule->silent || silent) { + cmd_options |= silent_mask; + } + if (rule->command_line->meta) { + cmd_options |= meta_mask; + } + if (!touch && (rule->command_line->hash.length > 0)) { + msg->appendCmd(new Avo_DmakeCommand(rule->command_line->string_mb, cmd_options)); + } + } + + xdr_msg = (RWCollectable*) msg; + xdr(&xdrs, xdr_msg); + (void) fflush(mtool_msgs_fp); + +/* tolik, 08/39/2002. + I commented out this code because it causes using unallocated memory. + delete msg; +*/ +} + +/* + * Append the stdout/err to Avo_MToolJobResultMsg. + */ +static void +append_job_result_msg(Avo_MToolJobResultMsg *job_result_msg) +{ + FILE *fp; + char line[MAXPATHLEN]; + char stdout_file2[MAXPATHLEN]; + + if (stdout_file != NULL) { + fp = fopen(stdout_file, "r"); + if (fp == NULL) { + /* Hmmm... what should we do here? */ + warning(catgets(catd, 1, 326, "fopen() of stdout_file failed. Output may be lost")); + return; + } + while (fgets(line, MAXPATHLEN, fp) != NULL) { + if (line[strlen(line) - 1] == '\n') { + line[strlen(line) - 1] = '\0'; + } + job_result_msg->appendOutput(AVO_STRDUP(line)); + } + (void) fclose(fp); + us_sleep(STAT_RETRY_SLEEP_TIME); + } else { + /* Hmmm... stdout_file shouldn't be NULL */ + warning(catgets(catd, 1, 327, "Internal stdout_file variable shouldn't be NULL. Output may be lost")); + } +} +#endif /* TEAMWARE_MAKE_CMN */ + +/* + * vpath_translation(cmd) + * + * Translates one command line by + * checking each word. If the word has an alias it is translated. + * + * Return value: + * The translated command + * + * Parameters: + * cmd Command to translate + * + * Global variables used: + */ +Name +vpath_translation(register Name cmd) +{ + wchar_t buffer[STRING_BUFFER_LENGTH]; + String_rec new_cmd; + wchar_t *p; + wchar_t *start; + + if (!vpath_defined || (cmd == NULL) || (cmd->hash.length == 0)) { + return cmd; + } + INIT_STRING_FROM_STACK(new_cmd, buffer); + + Wstring wcb(cmd); + p = wcb.get_string(); + + while (*p != (int) nul_char) { + while (iswspace(*p) && (*p != (int) nul_char)) { + append_char(*p++, &new_cmd); + } + start = p; + while (!iswspace(*p) && (*p != (int) nul_char)) { + p++; + } + cmd = GETNAME(start, p - start); + if (cmd->has_vpath_alias_prop) { + cmd = get_prop(cmd->prop, vpath_alias_prop)-> + body.vpath_alias.alias; + APPEND_NAME(cmd, + &new_cmd, + (int) cmd->hash.length); + } else { + append_string(start, &new_cmd, p - start); + } + } + cmd = GETNAME(new_cmd.buffer.start, FIND_LENGTH); + if (new_cmd.free_after_use) { + retmem(new_cmd.buffer.start); + } + return cmd; +} + +/* + * check_state(temp_file_name) + * + * Reads and checks the state changed by the previously executed command. + * + * Parameters: + * temp_file_name The auto dependency temp file + * + * Global variables used: + */ +void +check_state(Name temp_file_name) +{ + if (!keep_state) { + return; + } + + /* + * Then read the temp file that now might + * contain dependency reports from utilities + */ + read_dependency_file(temp_file_name); + + /* + * And reread .make.state if it + * changed (the command ran recursive makes) + */ + check_read_state_file(); + if (temp_file_name != NULL) { + (void) unlink(temp_file_name->string_mb); + } +} + +/* + * read_dependency_file(filename) + * + * Read the temp file used for reporting dependencies to make + * + * Parameters: + * filename The name of the file with the state info + * + * Global variables used: + * makefile_type The type of makefile being read + * read_trace_level Debug flag + * temp_file_number The always increasing number for unique files + * trace_reader Debug flag + */ +static void +read_dependency_file(register Name filename) +{ + register Makefile_type save_makefile_type; + + if (filename == NULL) { + return; + } + filename->stat.time = file_no_time; + if (exists(filename) > file_doesnt_exist) { + save_makefile_type = makefile_type; + makefile_type = reading_cpp_file; + if (read_trace_level > 1) { + trace_reader = true; + } + temp_file_number++; + (void) read_simple_file(filename, + false, + false, + false, + false, + false, + false); + trace_reader = false; + makefile_type = save_makefile_type; + } +} + +/* + * check_read_state_file() + * + * Check if .make.state has changed + * If it has we reread it + * + * Parameters: + * + * Global variables used: + * make_state Make state file name + * makefile_type Type of makefile being read + * read_trace_level Debug flag + * trace_reader Debug flag + */ +static void +check_read_state_file(void) +{ + timestruc_t previous = make_state->stat.time; + register Makefile_type save_makefile_type; + register Property makefile; + + make_state->stat.time = file_no_time; + if ((exists(make_state) == file_doesnt_exist) || + (make_state->stat.time == previous)) { + return; + } + save_makefile_type = makefile_type; + makefile_type = rereading_statefile; + /* Make sure we clear the old cached contents of .make.state */ + makefile = maybe_append_prop(make_state, makefile_prop); + if (makefile->body.makefile.contents != NULL) { + retmem(makefile->body.makefile.contents); + makefile->body.makefile.contents = NULL; + } + if (read_trace_level > 1) { + trace_reader = true; + } + temp_file_number++; + (void) read_simple_file(make_state, + false, + false, + false, + false, + false, + true); + trace_reader = false; + makefile_type = save_makefile_type; +} + +/* + * do_assign(line, target) + * + * Handles runtime assignments for command lines prefixed with "=". + * + * Parameters: + * line The command that contains an assignment + * target The Name of the target, used for error reports + * + * Global variables used: + * assign_done Set to indicate doname needs to reprocess + */ +static void +do_assign(register Name line, register Name target) +{ + Wstring wcb(line); + register wchar_t *string = wcb.get_string(); + register wchar_t *equal; + register Name name; + register Boolean append = false; + + /* + * If any runtime assignments are done, doname() must reprocess all + * targets in the future since the macro values used to build the + * command lines for the targets might have changed. + */ + assign_done = true; + /* Skip white space. */ + while (iswspace(*string)) { + string++; + } + equal = string; + /* Find "+=" or "=". */ + while (!iswspace(*equal) && + (*equal != (int) plus_char) && + (*equal != (int) equal_char)) { + equal++; + } + /* Internalize macro name. */ + name = GETNAME(string, equal - string); + /* Skip over "+=" "=". */ + while (!((*equal == (int) nul_char) || + (*equal == (int) equal_char) || + (*equal == (int) plus_char))) { + equal++; + } + switch (*equal) { + case nul_char: + fatal(catgets(catd, 1, 31, "= expected in rule `%s' for target `%s'"), + line->string_mb, + target->string_mb); + case plus_char: + append = true; + equal++; + break; + } + equal++; + /* Skip over whitespace in front of value. */ + while (iswspace(*equal)) { + equal++; + } + /* Enter new macro value. */ + enter_equal(name, + GETNAME(equal, wcb.get_string() + line->hash.length - equal), + append); +} + +/* + * build_command_strings(target, line) + * + * Builds the command string to used when + * building a target. If the string is different from the previous one + * is_out_of_date is set. + * + * Parameters: + * target Target to build commands for + * line Where to stuff result + * + * Global variables used: + * c_at The Name "@", used to set macro value + * command_changed Set if command is different from old + * debug_level Should we trace activities? + * do_not_exec_rule Always echo when running -n + * empty_name The Name "", used for empty rule + * funny Semantics of characters + * ignore_errors Used to init field for line + * is_conditional Set to false befor evaling macro, checked + * after expanding macros + * keep_state Indicates that .KEEP_STATE is on + * make_word_mentioned Set by macro eval, inits field for cmd + * query The Name "?", used to set macro value + * query_mentioned Set by macro eval, inits field for cmd + * recursion_level Used for tracing + * silent Used to init field for line + */ +static void +build_command_strings(Name target, register Property line) +{ + String_rec command_line; + register Cmd_line command_template = line->body.line.command_template; + register Cmd_line *insert = &line->body.line.command_used; + register Cmd_line used = *insert; + wchar_t buffer[STRING_BUFFER_LENGTH]; + wchar_t *start; + Name new_command_line; + register Boolean new_command_longer = false; + register Boolean ignore_all_command_dependency = true; + Property member; + static Name less_name; + static Name percent_name; + static Name star; + Name tmp_name; + + if (less_name == NULL) { + MBSTOWCS(wcs_buffer, "<"); + less_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, "%"); + percent_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, "*"); + star = GETNAME(wcs_buffer, FIND_LENGTH); + } + + /* We have to check if a target depends on conditional macros */ + /* Targets that do must be reprocessed by doname() each time around */ + /* since the macro values used when building the target might have */ + /* changed */ + conditional_macro_used = false; + /* If we are building a lib.a(member) target $@ should be bound */ + /* to lib.a */ + if (target->is_member && + ((member = get_prop(target->prop, member_prop)) != NULL)) { + target = member->body.member.library; + } + /* If we are building a "::" help target $@ should be bound to */ + /* the real target name */ + /* A lib.a(member) target is never :: */ + if (target->has_target_prop) { + target = get_prop(target->prop, target_prop)-> + body.target.target; + } + /* Bind the magic macros that make supplies */ + tmp_name = target; + if(tmp_name != NULL) { + if (tmp_name->has_vpath_alias_prop) { + tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> + body.vpath_alias.alias; + } + } + (void) SETVAR(c_at, tmp_name, false); + + tmp_name = line->body.line.star; + if(tmp_name != NULL) { + if (tmp_name->has_vpath_alias_prop) { + tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> + body.vpath_alias.alias; + } + } + (void) SETVAR(star, tmp_name, false); + + tmp_name = line->body.line.less; + if(tmp_name != NULL) { + if (tmp_name->has_vpath_alias_prop) { + tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> + body.vpath_alias.alias; + } + } + (void) SETVAR(less_name, tmp_name, false); + + tmp_name = line->body.line.percent; + if(tmp_name != NULL) { + if (tmp_name->has_vpath_alias_prop) { + tmp_name = get_prop(tmp_name->prop, vpath_alias_prop)-> + body.vpath_alias.alias; + } + } + (void) SETVAR(percent_name, tmp_name, false); + + /* $? is seldom used and it is expensive to build */ + /* so we store the list form and build the string on demand */ + Chain query_list = NULL; + Chain *query_list_tail = &query_list; + + for (Chain ch = line->body.line.query; ch != NULL; ch = ch->next) { + *query_list_tail = ALLOC(Chain); + (*query_list_tail)->name = ch->name; + if ((*query_list_tail)->name->has_vpath_alias_prop) { + (*query_list_tail)->name = + get_prop((*query_list_tail)->name->prop, + vpath_alias_prop)->body.vpath_alias.alias; + } + (*query_list_tail)->next = NULL; + query_list_tail = &(*query_list_tail)->next; + } + (void) setvar_daemon(query, + (Name) query_list, + false, + chain_daemon, + false, + debug_level); + + /* build $^ */ + Chain hat_list = NULL; + Chain *hat_list_tail = &hat_list; + + for (Dependency dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + /* skip automatic dependencies */ + if (!dependency->automatic) { + if ((dependency->name != force) && + (dependency->stale == false)) { + *hat_list_tail = ALLOC(Chain); + + if (dependency->name->is_member && + (get_prop(dependency->name->prop, member_prop) != NULL)) { + (*hat_list_tail)->name = + get_prop(dependency->name->prop, + member_prop)->body.member.member; + } else { + (*hat_list_tail)->name = dependency->name; + } + + if((*hat_list_tail)->name != NULL) { + if ((*hat_list_tail)->name->has_vpath_alias_prop) { + (*hat_list_tail)->name = + get_prop((*hat_list_tail)->name->prop, + vpath_alias_prop)->body.vpath_alias.alias; + } + } + + (*hat_list_tail)->next = NULL; + hat_list_tail = &(*hat_list_tail)->next; + } + } + } + (void) setvar_daemon(hat, + (Name) hat_list, + false, + chain_daemon, + false, + debug_level); + +/* We have two command sequences we need to handle */ +/* The old one that we probably read from .make.state */ +/* and the new one we are building that will replace the old one */ +/* Even when KEEP_STATE is not on we build a new command sequence and store */ +/* it in the line prop. This command sequence is then executed by */ +/* run_command(). If KEEP_STATE is on it is also later written to */ +/* .make.state. The routine replaces the old command line by line with the */ +/* new one trying to reuse Cmd_lines */ + + /* If there is no old command_used we have to start creating */ + /* Cmd_lines to keep the new cmd in */ + if (used == NULL) { + new_command_longer = true; + *insert = used = ALLOC(Cmd_line); + used->next = NULL; + used->command_line = NULL; + insert = &used->next; + } + /* Run thru the template for the new command and build the expanded */ + /* new command lines */ + for (; + command_template != NULL; + command_template = command_template->next, insert = &used->next, used = *insert) { + /* If there is no old command_used Cmd_line we need to */ + /* create one and say that cmd consistency failed */ + if (used == NULL) { + new_command_longer = true; + *insert = used = ALLOC(Cmd_line); + used->next = NULL; + used->command_line = empty_name; + } + /* Prepare the Cmd_line for the processing */ + /* The command line prefixes "@-=?" are stripped and that */ + /* information is saved in the Cmd_line */ + used->assign = false; + used->ignore_error = ignore_errors; + used->silent = silent; + used->always_exec = false; + /* Expand the macros in the command line */ + INIT_STRING_FROM_STACK(command_line, buffer); + make_word_mentioned = + query_mentioned = + false; + expand_value(command_template->command_line, &command_line, true); + /* If the macro $(MAKE) is mentioned in the command */ + /* "make -n" runs actually execute the command */ + used->make_refd = make_word_mentioned; + used->ignore_command_dependency = query_mentioned; + /* Strip the prefixes */ + start = command_line.buffer.start; + for (; + iswspace(*start) || + (get_char_semantics_value(*start) & (int) command_prefix_sem); + start++) { + switch (*start) { + case question_char: + used->ignore_command_dependency = true; + break; + case exclam_char: + used->ignore_command_dependency = false; + break; + case equal_char: + used->assign = true; + break; + case hyphen_char: + used->ignore_error = true; + break; + case at_char: + if (!do_not_exec_rule) { + used->silent = true; + } + break; + case plus_char: + if(posix) { + used->always_exec = true; + } + break; + } + } + /* If all command lines of the template are prefixed with "?"*/ + /* the VIRTUAL_ROOT is not used for cmd consistency checks */ + if (!used->ignore_command_dependency) { + ignore_all_command_dependency = false; + } + /* Internalize the expanded and stripped command line */ + new_command_line = GETNAME(start, FIND_LENGTH); + if ((used->command_line == NULL) && + (line->body.line.sccs_command)) { + used->command_line = new_command_line; + new_command_longer = false; + } + /* Compare it with the old one for command consistency */ + if (used->command_line != new_command_line) { + Name vpath_translated = vpath_translation(new_command_line); + if (keep_state && + !used->ignore_command_dependency && (vpath_translated != used->command_line)) { + if (debug_level > 0) { + if (used->command_line != NULL + && *used->command_line->string_mb != + '\0') { + (void) printf(catgets(catd, 1, 32, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from old\n\t%s\n"), + recursion_level, + "", + target->string_mb, + vpath_translated->string_mb, + recursion_level, + "", + used-> + command_line-> + string_mb); + } else { + (void) printf(catgets(catd, 1, 33, "%*sBuilding %s because new command \n\t%s\n%*sdifferent from empty old command\n"), + recursion_level, + "", + target->string_mb, + vpath_translated->string_mb, + recursion_level, + ""); + } + } + command_changed = true; + line->body.line.is_out_of_date = true; + } + used->command_line = new_command_line; + } + if (command_line.free_after_use) { + retmem(command_line.buffer.start); + } + } + /* Check if the old command is longer than the new for */ + /* command consistency */ + if (used != NULL) { + *insert = NULL; + if (keep_state && + !ignore_all_command_dependency) { + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 34, "%*sBuilding %s because new command shorter than old\n"), + recursion_level, + "", + target->string_mb); + } + command_changed = true; + line->body.line.is_out_of_date = true; + } + } + /* Check if the new command is longer than the old command for */ + /* command consistency */ + if (new_command_longer && + !ignore_all_command_dependency && + keep_state) { + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 35, "%*sBuilding %s because new command longer than old\n"), + recursion_level, + "", + target->string_mb); + } + command_changed = true; + line->body.line.is_out_of_date = true; + } + /* Unbind the magic macros */ + (void) SETVAR(c_at, (Name) NULL, false); + (void) SETVAR(star, (Name) NULL, false); + (void) SETVAR(less_name, (Name) NULL, false); + (void) SETVAR(percent_name, (Name) NULL, false); + (void) SETVAR(query, (Name) NULL, false); + if (query_list != NULL) { + delete_query_chain(query_list); + } + (void) SETVAR(hat, (Name) NULL, false); + if (hat_list != NULL) { + delete_query_chain(hat_list); + } + + if (conditional_macro_used) { + target->conditional_macro_list = cond_macro_list; + cond_macro_list = NULL; + target->depends_on_conditional = true; + } +} + +/* + * touch_command(line, target, result) + * + * If this is an "make -t" run we do this. + * We touch all targets in the target group ("foo + fie:") if any. + * + * Return value: + * Indicates if the command failed or not + * + * Parameters: + * line The command line to update + * target The target we are touching + * result Initial value for the result we return + * + * Global variables used: + * do_not_exec_rule Indicates that -n is on + * silent Do not echo commands + */ +static Doname +touch_command(register Property line, register Name target, Doname result) +{ + Name name; + register Chain target_group; + String_rec touch_string; + wchar_t buffer[MAXPATHLEN]; + Name touch_cmd; + Cmd_line rule; + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + Avo_MToolJobResultMsg *job_result_msg; + RWCollectable *xdr_msg; + int child_pid = 0; + wchar_t string[MAXPATHLEN]; + char mbstring[MAXPATHLEN]; + int filed; +#endif + + SEND_MTOOL_MSG( + if (!sent_rsrc_info_msg) { + if (userName[0] == '\0') { + avo_get_user(userName, NULL); + } + if (hostName[0] == '\0') { + strcpy(hostName, avo_hostname()); + } + send_rsrc_info_msg(1, hostName, userName); + sent_rsrc_info_msg = 1; + } + send_job_start_msg(line); + job_result_msg = new Avo_MToolJobResultMsg(); + ); + for (name = target, target_group = NULL; name != NULL;) { + if (!name->is_member) { + /* + * Build a touch command that can be passed + * to dosys(). If KEEP_STATE is on, "make -t" + * will save the proper command, not the + * "touch" in .make.state. + */ + INIT_STRING_FROM_STACK(touch_string, buffer); + MBSTOWCS(wcs_buffer, NOCATGETS("touch ")); + append_string(wcs_buffer, &touch_string, FIND_LENGTH); + touch_cmd = name; + if (name->has_vpath_alias_prop) { + touch_cmd = get_prop(name->prop, + vpath_alias_prop)-> + body.vpath_alias.alias; + } + APPEND_NAME(touch_cmd, + &touch_string, + FIND_LENGTH); + touch_cmd = GETNAME(touch_string.buffer.start, + FIND_LENGTH); + if (touch_string.free_after_use) { + retmem(touch_string.buffer.start); + } + if (!silent || + do_not_exec_rule && + (target_group == NULL)) { + (void) printf("%s\n", touch_cmd->string_mb); + SEND_MTOOL_MSG( + job_result_msg->appendOutput(AVO_STRDUP(touch_cmd->string_mb)); + ); + } + /* Run the touch command, or simulate it */ + if (!do_not_exec_rule) { + + SEND_MTOOL_MSG( + (void) sprintf(mbstring, + NOCATGETS("%s/make.stdout.%d.%d.XXXXXX"), + tmpdir, + getpid(), + file_number++); + + int tmp_fd = mkstemp(mbstring); + if(tmp_fd) { + (void) close(tmp_fd); + } + + stdout_file = strdup(mbstring); + stderr_file = NULL; + child_pid = pollResults(stdout_file, + (char *)NULL, + (char *)NULL); + ); + + result = dosys(touch_cmd, + false, + false, + false, + false, + name, + send_mtool_msgs); + + SEND_MTOOL_MSG( + append_job_result_msg(job_result_msg); + if (child_pid > 0) { + kill(child_pid, SIGUSR1); + while (!((waitpid(child_pid, 0, 0) == -1) + && (errno == ECHILD))); + } + child_pid = 0; + (void) unlink(stdout_file); + retmem_mb(stdout_file); + stdout_file = NULL; + ); + + } else { + result = build_ok; + } + } else { + result = build_ok; + } + if (target_group == NULL) { + target_group = line->body.line.target_group; + } else { + target_group = target_group->next; + } + if (target_group != NULL) { + name = target_group->name; + } else { + name = NULL; + } + } + SEND_MTOOL_MSG( + job_result_msg->setResult(job_msg_id, (result == build_ok) ? 0 : 1, DONE); + xdr_msg = (RWCollectable*) job_result_msg; + xdr(&xdrs, xdr_msg); + (void) fflush(mtool_msgs_fp); + delete job_result_msg; + ); + return result; +} + +/* + * update_target(line, result) + * + * updates the status of a target after executing its commands. + * + * Parameters: + * line The command line block to update + * result Indicates that build is OK so can update + * + * Global variables used: + * do_not_exec_rule Indicates that -n is on + * touch Fake the new timestamp if we are just touching + */ +void +update_target(Property line, Doname result) +{ + Name target; + Chain target_group; + Property line2; + timestruc_t old_stat_time; + Property member; + + /* + * [tolik] Additional fix for bug 1063790. It was fixed + * for serial make long ago, but DMake dumps core when + * target is a symlink and sccs file is newer then target. + * In this case, finish_children() calls update_target() + * with line==NULL. + */ + if(line == NULL) { + /* XXX. Should we do anything here? */ + return; + } + + target = line->body.line.target; + + if ((result == build_ok) && (line->body.line.command_used != NULL)) { + if (do_not_exec_rule || + touch || + (target->is_member && + (line->body.line.command_template != NULL) && + (line->body.line.command_template->command_line->string_mb[0] == 0) && + (line->body.line.command_template->next == NULL))) { + /* If we are simulating execution we need to fake a */ + /* new timestamp for the target we didnt build */ + target->stat.time = file_max_time; + } else { + /* + * If we really built the target we read the new + * timestamp. + * Fix for bug #1110906: if .c file is newer than + * the corresponding .o file which is in an archive + * file, make will compile the .c file but it won't + * update the object in the .a file. + */ + old_stat_time = target->stat.time; + target->stat.time = file_no_time; + (void) exists(target); + if ((target->is_member) && + (target->stat.time == old_stat_time)) { + member = get_prop(target->prop, member_prop); + if (member != NULL) { + target->stat.time = member->body.member.library->stat.time; + target->stat.time.tv_sec++; + } + } + } + /* If the target is part of a group we need to propagate the */ + /* result of the run to all members */ + for (target_group = line->body.line.target_group; + target_group != NULL; + target_group = target_group->next) { + target_group->name->stat.time = target->stat.time; + line2 = maybe_append_prop(target_group->name, + line_prop); + line2->body.line.command_used = + line->body.line.command_used; + line2->body.line.target = target_group->name; + } + } + target->has_built = true; +} + +/* + * sccs_get(target, command) + * + * Figures out if it possible to sccs get a file + * and builds the command to do it if it is. + * + * Return value: + * Indicates if sccs get failed or not + * + * Parameters: + * target Target to get + * command Where to deposit command to use + * + * Global variables used: + * debug_level Should we trace activities? + * recursion_level Used for tracing + * sccs_get_rule The rule to used for sccs getting + */ +static Doname +sccs_get(register Name target, register Property *command) +{ + register int result; + char link[MAXPATHLEN]; + String_rec string; + wchar_t name[MAXPATHLEN]; + register wchar_t *p; + timestruc_t sccs_time; + register Property line; + int sym_link_depth = 0; + + /* For sccs, we need to chase symlinks. */ + while (target->stat.is_sym_link) { + if (sym_link_depth++ > 90) { + fatal(catgets(catd, 1, 95, "Can't read symbolic link `%s': Number of symbolic links encountered during path name traversal exceeds 90."), + target->string_mb); + } + /* Read the value of the link. */ + result = readlink_vroot(target->string_mb, + link, + sizeof(link), + NULL, + VROOT_DEFAULT); + if (result == -1) { + fatal(catgets(catd, 1, 36, "Can't read symbolic link `%s': %s"), + target->string_mb, errmsg(errno)); + } + link[result] = 0; + /* Use the value to build the proper filename. */ + INIT_STRING_FROM_STACK(string, name); + + Wstring wcb(target); + if ((link[0] != slash_char) && + ((p = (wchar_t *) wsrchr(wcb.get_string(), slash_char)) != NULL)) { + append_string(wcb.get_string(), &string, p - wcb.get_string() + 1); + } + append_string(link, &string, result); + /* Replace the old name with the translated name. */ + target = normalize_name(string.buffer.start, string.text.p - string.buffer.start); + (void) exists(target); + if (string.free_after_use) { + retmem(string.buffer.start); + } + } + + /* + * read_dir() also reads the ?/SCCS dir and saves information + * about which files have SCSC/s. files. + */ + if (target->stat.has_sccs == DONT_KNOW_SCCS) { + read_directory_of_file(target); + } + switch (target->stat.has_sccs) { + case DONT_KNOW_SCCS: + /* We dont know by now there is no SCCS/s.* */ + target->stat.has_sccs = NO_SCCS; + case NO_SCCS: + /* + * If there is no SCCS/s.* but the plain file exists, + * we say things are OK. + */ + if (target->stat.time > file_doesnt_exist) { + return build_ok; + } + /* If we cant find the plain file, we give up. */ + return build_dont_know; + case HAS_SCCS: + /* + * Pay dirt. We now need to figure out if the plain file + * is out of date relative to the SCCS/s.* file. + */ + sccs_time = exists(get_prop(target->prop, + sccs_prop)->body.sccs.file); + break; + } + + if ((!target->has_complained && + (sccs_time != file_doesnt_exist) && + (sccs_get_rule != NULL))) { + /* only checking */ + if (command == NULL) { + return build_ok; + } + /* + * We provide a command line for the target. The line is a + * "sccs get" command from default.mk. + */ + line = maybe_append_prop(target, line_prop); + *command = line; + if (sccs_time > target->stat.time) { + /* + * And only if the plain file is out of date do we + * request execution of the command. + */ + line->body.line.is_out_of_date = true; + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 37, "%*sSccs getting %s because s. file is younger than source file\n"), + recursion_level, + "", + target->string_mb); + } + } + line->body.line.sccs_command = true; + line->body.line.command_template = sccs_get_rule; + if(!svr4 && (!allrules_read || posix)) { + if((target->prop) && + (target->prop->body.sccs.file) && + (target->prop->body.sccs.file->string_mb)) { + if((strlen(target->prop->body.sccs.file->string_mb) == + strlen(target->string_mb) + 2) && + (target->prop->body.sccs.file->string_mb[0] == 's') && + (target->prop->body.sccs.file->string_mb[1] == '.')) { + + line->body.line.command_template = get_posix_rule; + } + } + } + line->body.line.target = target; + /* + * Also make sure the rule is build with $* and $< + * bound properly. + */ + line->body.line.star = NULL; + line->body.line.less = NULL; + line->body.line.percent = NULL; + return build_ok; + } + return build_dont_know; +} + +/* + * read_directory_of_file(file) + * + * Reads the directory the specified file lives in. + * + * Parameters: + * file The file we need to read dir for + * + * Global variables used: + * dot The Name ".", used as the default dir + */ +void +read_directory_of_file(register Name file) +{ + + Wstring file_string(file); + wchar_t * wcb = file_string.get_string(); + wchar_t usr_include_buf[MAXPATHLEN]; + wchar_t usr_include_sys_buf[MAXPATHLEN]; + + register Name directory = dot; + register wchar_t *p = (wchar_t *) wsrchr(wcb, + (int) slash_char); + register int length = p - wcb; + static Name usr_include; + static Name usr_include_sys; + + if (usr_include == NULL) { + MBSTOWCS(usr_include_buf, NOCATGETS("/usr/include")); + usr_include = GETNAME(usr_include_buf, FIND_LENGTH); + MBSTOWCS(usr_include_sys_buf, NOCATGETS("/usr/include/sys")); + usr_include_sys = GETNAME(usr_include_sys_buf, FIND_LENGTH); + } + + /* + * If the filename contains a "/" we have to extract the path + * Else the path defaults to ".". + */ + if (p != NULL) { + /* + * Check some popular directories first to possibly + * save time. Compare string length first to gain speed. + */ + if ((usr_include->hash.length == length) && + IS_WEQUALN(usr_include_buf, + wcb, + length)) { + directory = usr_include; + } else if ((usr_include_sys->hash.length == length) && + IS_WEQUALN(usr_include_sys_buf, + wcb, + length)) { + directory = usr_include_sys; + } else { + directory = GETNAME(wcb, length); + } + } + (void) read_dir(directory, + (wchar_t *) NULL, + (Property) NULL, + (wchar_t *) NULL); +} + +/* + * add_pattern_conditionals(target) + * + * Scan the list of conditionals defined for pattern targets and add any + * that match this target to its list of conditionals. + * + * Parameters: + * target The target we should add conditionals for + * + * Global variables used: + * conditionals The list of pattern conditionals + */ +static void +add_pattern_conditionals(register Name target) +{ + register Property conditional; + Property new_prop; + Property *previous; + Name_rec dummy; + wchar_t *pattern; + wchar_t *percent; + int length; + + Wstring wcb(target); + Wstring wcb1; + + for (conditional = get_prop(conditionals->prop, conditional_prop); + conditional != NULL; + conditional = get_prop(conditional->next, conditional_prop)) { + wcb1.init(conditional->body.conditional.target); + pattern = wcb1.get_string(); + if (pattern[1] != 0) { + percent = (wchar_t *) wschr(pattern, (int) percent_char); + if (!wcb.equaln(pattern, percent-pattern) || + !IS_WEQUAL(wcb.get_string(wcb.length()-wslen(percent+1)), percent+1)) { + continue; + } + } + for (previous = &target->prop; + *previous != NULL; + previous = &(*previous)->next) { + if (((*previous)->type == conditional_prop) && + ((*previous)->body.conditional.sequence > + conditional->body.conditional.sequence)) { + break; + } + } + if (*previous == NULL) { + new_prop = append_prop(target, conditional_prop); + } else { + dummy.prop = NULL; + new_prop = append_prop(&dummy, conditional_prop); + new_prop->next = *previous; + *previous = new_prop; + } + target->conditional_cnt++; + new_prop->body.conditional = conditional->body.conditional; + } +} + +/* + * set_locals(target, old_locals) + * + * Sets any conditional macros for the target. + * Each target carries a possibly empty set of conditional properties. + * + * Parameters: + * target The target to set conditional macros for + * old_locals Space to store old values in + * + * Global variables used: + * debug_level Should we trace activity? + * is_conditional We need to preserve this value + * recursion_level Used for tracing + */ +void +set_locals(register Name target, register Property old_locals) +{ + register Property conditional; + register int i; + register Boolean saved_conditional_macro_used; + Chain cond_name; + Chain cond_chain; + +#ifdef DISTRIBUTED + if (target->dont_activate_cond_values) { + return; + } +#endif + + saved_conditional_macro_used = conditional_macro_used; + + /* Scan the list of conditional properties and apply each one */ + for (conditional = get_prop(target->prop, conditional_prop), i = 0; + conditional != NULL; + conditional = get_prop(conditional->next, conditional_prop), + i++) { + /* Save the old value */ + old_locals[i].body.macro = + maybe_append_prop(conditional->body.conditional.name, + macro_prop)->body.macro; + if (debug_level > 1) { + (void) printf(catgets(catd, 1, 38, "%*sActivating conditional value: "), + recursion_level, + ""); + } + /* Set the conditional value. Macros are expanded when the */ + /* macro is refd as usual */ + if ((conditional->body.conditional.name != virtual_root) || + (conditional->body.conditional.value != virtual_root)) { + (void) SETVAR(conditional->body.conditional.name, + conditional->body.conditional.value, + (Boolean) conditional->body.conditional.append); + } + cond_name = ALLOC(Chain); + cond_name->name = conditional->body.conditional.name; + } + /* Put this target on the front of the chain of conditional targets */ + cond_chain = ALLOC(Chain); + cond_chain->name = target; + cond_chain->next = conditional_targets; + conditional_targets = cond_chain; + conditional_macro_used = saved_conditional_macro_used; +} + +/* + * reset_locals(target, old_locals, conditional, index) + * + * Removes any conditional macros for the target. + * + * Parameters: + * target The target we are retoring values for + * old_locals The values to restore + * conditional The first conditional block for the target + * index into the old_locals vector + * Global variables used: + * debug_level Should we trace activities? + * recursion_level Used for tracing + */ +void +reset_locals(register Name target, register Property old_locals, register Property conditional, register int index) +{ + register Property this_conditional; + Chain cond_chain; + +#ifdef DISTRIBUTED + if (target->dont_activate_cond_values) { + return; + } +#endif + + /* Scan the list of conditional properties and restore the old value */ + /* to each one Reverse the order relative to when we assigned macros */ + this_conditional = get_prop(conditional->next, conditional_prop); + if (this_conditional != NULL) { + reset_locals(target, old_locals, this_conditional, index+1); + } else { + /* Remove conditional target from chain */ + if (conditional_targets == NULL || + conditional_targets->name != target) { + warning(catgets(catd, 1, 39, "Internal error: reset target not at head of condtional_targets chain")); + } else { + cond_chain = conditional_targets->next; + retmem_mb((caddr_t) conditional_targets); + conditional_targets = cond_chain; + } + } + get_prop(conditional->body.conditional.name->prop, + macro_prop)->body.macro = old_locals[index].body.macro; + if (conditional->body.conditional.name == virtual_root) { + (void) SETVAR(virtual_root, getvar(virtual_root), false); + } + if (debug_level > 1) { + if (old_locals[index].body.macro.value != NULL) { + (void) printf(catgets(catd, 1, 40, "%*sdeactivating conditional value: %s= %s\n"), + recursion_level, + "", + conditional->body.conditional.name-> + string_mb, + old_locals[index].body.macro.value-> + string_mb); + } else { + (void) printf(catgets(catd, 1, 41, "%*sdeactivating conditional value: %s =\n"), + recursion_level, + "", + conditional->body.conditional.name-> + string_mb); + } + } +} + +/* + * check_auto_dependencies(target, auto_count, automatics) + * + * Returns true if the target now has a dependency + * it didn't previously have (saved on automatics). + * + * Return value: + * true if new dependency found + * + * Parameters: + * target Target we check + * auto_count Number of old automatic vars + * automatics Saved old automatics + * + * Global variables used: + * keep_state Indicates that .KEEP_STATE is on + */ +Boolean +check_auto_dependencies(Name target, int auto_count, Name *automatics) +{ + Name *p; + int n; + Property line; + Dependency dependency; + + if (keep_state) { + if ((line = get_prop(target->prop, line_prop)) == NULL) { + return false; + } + /* Go thru new list of automatic depes */ + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + /* And make sure that each one existed before we */ + /* built the target */ + if (dependency->automatic && !dependency->stale) { + for (n = auto_count, p = automatics; + n > 0; + n--) { + if (*p++ == dependency->name) { + /* If we can find it on the */ + /* saved list of autos we */ + /* are OK */ + goto not_new; + } + } + /* But if we scan over the old list */ + /* of auto. without finding it it is */ + /* new and we must check it */ + return true; + } + not_new:; + } + return false; + } else { + return false; + } +} + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +void +create_xdrs_ptr(void) +{ + static int xdrs_init = 0; + + if (!xdrs_init) { + xdrs_init = 1; + mtool_msgs_fp = fdopen(mtool_msgs_fd, "a"); + xdrstdio_create(&xdrs, + mtool_msgs_fp, + XDR_ENCODE); + } +} + +XDR * +get_xdrs_ptr(void) +{ + return &xdrs; +} + +FILE * +get_mtool_msgs_fp(void) +{ + return mtool_msgs_fp; +} + +int +get_job_msg_id(void) +{ + return job_msg_id; +} + +// Continuously poll and show the results of remotely executing a job, +// i.e., output the stdout and stderr files. + +static int +pollResults(char *outFn, char *errFn, char *hostNm) +{ + int child; + + child = fork(); + switch (child) { + case -1: + break; + case 0: + enable_interrupt((void (*) (int))SIG_DFL); +#ifdef linux + (void) signal(SIGUSR1, Avo_PollResultsAction_Sigusr1Handler); +#else + (void) sigset(SIGUSR1, Avo_PollResultsAction_Sigusr1Handler); +#endif + pollResultsAction(outFn, errFn); + + exit(0); + break; + default: + break; + } + return child; +} + +// This is the PollResultsAction SIGUSR1 handler. + +static bool_t pollResultsActionTimeToFinish = FALSE; + +extern "C" void +Avo_PollResultsAction_Sigusr1Handler(int foo) +{ + pollResultsActionTimeToFinish = TRUE; +} + +static void +pollResultsAction(char *outFn, char *errFn) +{ + int fd; + time_t file_time = 0; + long file_time_nsec = 0; + struct stat statbuf; + int stat_rc; + + // Keep stat'ing until file exists. + while (((stat_rc = stat(outFn, &statbuf)) != 0) && + (errno == ENOENT) && + !pollResultsActionTimeToFinish) { + us_sleep(STAT_RETRY_SLEEP_TIME); + } + // The previous stat() could be failed due to EINTR + // So one more try is needed + if (stat_rc != 0 && stat(outFn, &statbuf) != 0) { + // stat() failed + warning(NOCATGETS("Internal error: stat(\"%s\", ...) failed: %s\n"), + outFn, strerror(errno)); + exit(1); + } + + if ((fd = open(outFn, O_RDONLY)) < 0 + && (errno != EINTR || (fd = open(outFn, O_RDONLY)) < 0)) { + // open() failed + warning(NOCATGETS("Internal error: open(\"%s\", O_RDONLY) failed: %s\n"), + outFn, strerror(errno)); + exit(1); + } + + while (!pollResultsActionTimeToFinish && stat(outFn, &statbuf) == 0) { +#ifdef linux + if ((statbuf.st_mtime > file_time) + ) { + file_time = statbuf.st_mtime; + rxmGetNextResultsBlock(fd); + } +#else + if ((statbuf.st_mtim.tv_sec > file_time) || + ((statbuf.st_mtim.tv_sec == file_time) && + (statbuf.st_mtim.tv_nsec > file_time_nsec)) + ) { + file_time = statbuf.st_mtim.tv_sec; + file_time_nsec = statbuf.st_mtim.tv_nsec; + rxmGetNextResultsBlock(fd); + } +#endif + us_sleep(STAT_RETRY_SLEEP_TIME); + } + // Check for the rest of output + rxmGetNextResultsBlock(fd); + + (void) close(fd); +} + +static void +rxmGetNextResultsBlock(int fd) +{ + size_t to_read = 8 * 1024; + ssize_t bytes_read; + ssize_t bytes_written; + char results_buf[8 * 1024]; + sigset_t newset; + sigset_t oldset; + + // Read some more from the output/results file. + // Hopefully the kernel managed to prefetch the stuff. + bytes_read = read(fd, results_buf, to_read); + while (bytes_read > 0) { + AVO_BLOCK_INTERUPTS; + bytes_written = write(1, results_buf, bytes_read); + AVO_UNBLOCK_INTERUPTS; + if (bytes_written != bytes_read) { + // write() failed + warning(NOCATGETS("Internal error: write(1, ...) failed: %s\n"), + strerror(errno)); + exit(1); + } + bytes_read = read(fd, results_buf, to_read); + } +} + +// Generic, interruptable microsecond resolution sleep member function. + +static int +us_sleep(unsigned int nusecs) +{ + struct pollfd dummy; + int timeout; + + if ((timeout = nusecs/1000) <= 0) { + timeout = 1; + } + return poll(&dummy, 0, timeout); +} +#endif /* TEAMWARE_MAKE_CMN */ + +// Recursively delete each of the Chain struct on the chain. + +static void +delete_query_chain(Chain ch) +{ + if (ch == NULL) { + return; + } else { + delete_query_chain(ch->next); + retmem_mb((char *) ch); + } +} + +Doname +target_can_be_built(register Name target) { + Doname result = build_dont_know; + Name true_target = target; + Property line; + + if (target == wait_name) { + return(build_ok); + } + /* + * If the target is a constructed one for a "::" target, + * we need to consider that. + */ + if (target->has_target_prop) { + true_target = get_prop(target->prop, + target_prop)->body.target.target; + } + + (void) exists(true_target); + + if (true_target->state == build_running) { + return(build_running); + } + if (true_target->stat.time != file_doesnt_exist) { + result = build_ok; + } + + /* get line property for the target */ + line = get_prop(true_target->prop, line_prop); + + /* first check for explicit rule */ + if (line != NULL && line->body.line.command_template != NULL) { + result = build_ok; + } + /* try to find pattern rule */ + if (result == build_dont_know) { + result = find_percent_rule(target, NULL, false); + } + + /* try to find double suffix rule */ + if (result == build_dont_know) { + if (target->is_member) { + Property member = get_prop(target->prop, member_prop); + if (member != NULL && member->body.member.member != NULL) { + result = find_ar_suffix_rule(target, member->body.member.member, NULL, false); + } else { + result = find_double_suffix_rule(target, NULL, false); + } + } else { + result = find_double_suffix_rule(target, NULL, false); + } + } + + /* try to find suffix rule */ + if ((result == build_dont_know) && second_pass) { + result = find_suffix_rule(target, target, empty_name, NULL, false); + } + + /* check for sccs */ + if (result == build_dont_know) { + result = sccs_get(target, NULL); + } + + /* try to find dyn target */ + if (result == build_dont_know) { + Name dtarg = find_dyntarget(target); + if (dtarg != NULL) { + result = target_can_be_built(dtarg); + } + } + + /* check whether target was mentioned in makefile */ + if (result == build_dont_know) { + if (target->colons != no_colon) { + result = build_ok; + } + } + + /* result */ + return result; +} diff --git a/usr/src/make_src/Make/bin/make/common/dosys.cc b/usr/src/make_src/Make/bin/make/common/dosys.cc new file mode 100644 index 0000000..de9b043 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/dosys.cc @@ -0,0 +1,174 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)dosys.cc 1.45 06/12/12 + */ + +#pragma ident "@(#)dosys.cc 1.45 06/12/12" + +/* + * dosys.cc + * + * Execute one commandline + */ + +/* + * Included files + */ +#include <fcntl.h> /* open() */ +#include <mk/defs.h> +#include <mksh/dosys.h> /* doshell(), doexec() */ +#include <mksh/misc.h> /* getmem() */ +#include <sys/stat.h> /* open() */ +#include <unistd.h> /* getpid() */ + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +static int filter_file; +static char *filter_file_name; + +/* + * File table of contents + */ +static void redirect_stderr(void); + +/* + * dosys(command, ignore_error, call_make, silent_error, target) + * + * Check if command string contains meta chars and dispatch to + * the proper routine for executing one command line. + * + * Return value: + * Indicates if the command execution failed + * + * Parameters: + * command The command to run + * ignore_error Should make abort when an error is seen? + * call_make Did command reference $(MAKE) ? + * silent_error Should error messages be suppressed for pmake? + * target Target we are building + * + * Global variables used: + * do_not_exec_rule Is -n on? + * working_on_targets We started processing real targets + */ +Doname +dosys(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err) +{ + timestruc_t before; + register int length = command->hash.length; + Wstring wcb(command); + register wchar_t *p = wcb.get_string(); + register wchar_t *q; + Doname result; + + /* Strip spaces from head of command string */ + while (iswspace(*p)) { + p++, length--; + } + if (*p == (int) nul_char) { + return build_failed; + } + /* If we are faking it we just return */ + if (do_not_exec_rule && + working_on_targets && + !call_make && + !always_exec) { + return build_ok; + } + /* no_action_was_taken is used to print special message */ + no_action_was_taken = false; + + /* Copy string to make it OK to write it. */ + q = ALLOC_WC(length + 1); + (void) wscpy(q, p); + /* Write the state file iff this command uses make. */ + if (call_make && command_changed) { + write_state_file(0, false); + } + make_state->stat.time = file_no_time; + (void)exists(make_state); + before = make_state->stat.time; + /* + * Run command directly if it contains no shell meta chars, + * else run it using the shell. + */ + if (await(ignore_error, + silent_error, + target, + wcb.get_string(), + command->meta ? + doshell(q, ignore_error, redirect_out_err, + stdout_file, stderr_file, 0) : + doexec(q, ignore_error, redirect_out_err, + stdout_file, stderr_file, + vroot_path, 0), + send_mtool_msgs, +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + get_xdrs_ptr(), + get_job_msg_id() +#else + NULL, + -1 +#endif + )) { + result = build_ok; + } else { + result = build_failed; + } + retmem(q); + + if ((report_dependencies_level == 0) && + call_make) { + make_state->stat.time = file_no_time; + (void)exists(make_state); + if (before == make_state->stat.time) { + return result; + } + makefile_type = reading_statefile; + if (read_trace_level > 1) { + trace_reader = true; + } + temp_file_number++; + (void) read_simple_file(make_state, + false, + false, + false, + false, + false, + true); + trace_reader = false; + } + return result; +} diff --git a/usr/src/make_src/Make/bin/make/common/files.cc b/usr/src/make_src/Make/bin/make/common/files.cc new file mode 100644 index 0000000..6ca6919 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/files.cc @@ -0,0 +1,733 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)files.cc 1.37 06/12/12 + */ + +#pragma ident "@(#)files.cc 1.37 06/12/12" + +/* + * files.c + * + * Various file related routines: + * Figure out if file exists + * Wildcard resolution for directory reader + * Directory reader + */ + + +/* + * Included files + */ +#if defined(SUN5_0) || defined(HP_UX) +#include <dirent.h> /* opendir() */ +#else +#include <sys/dir.h> /* opendir() */ +#endif +#include <errno.h> /* errno */ +#include <mk/defs.h> +#include <mksh/macro.h> /* getvar() */ +#include <mksh/misc.h> /* get_prop(), append_prop() */ +#include <sys/stat.h> /* lstat() */ + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +/* + * File table of contents + */ +extern timestruc_t& exists(register Name target); +extern void set_target_stat(register Name target, struct stat buf); +static timestruc_t& vpath_exists(register Name target); +static Name enter_file_name(wchar_t *name_string, wchar_t *library); +static Boolean star_match(register char *string, register char *pattern); +static Boolean amatch(register wchar_t *string, register wchar_t *pattern); + +/* + * exists(target) + * + * Figure out the timestamp for one target. + * + * Return value: + * The time the target was created + * + * Parameters: + * target The target to check + * + * Global variables used: + * debug_level Should we trace the stat call? + * recursion_level Used for tracing + * vpath_defined Was the variable VPATH defined in environment? + */ +timestruc_t& +exists(register Name target) +{ + struct stat buf; + register int result; + + /* We cache stat information. */ + if (target->stat.time != file_no_time) { + return target->stat.time; + } + + /* + * If the target is a member, we have to extract the time + * from the archive. + */ + if (target->is_member && + (get_prop(target->prop, member_prop) != NULL)) { + return read_archive(target); + } + + if (debug_level > 1) { + (void) printf(NOCATGETS("%*sstat(%s)\n"), + recursion_level, + "", + target->string_mb); + } + + result = lstat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT); + if ((result != -1) && ((buf.st_mode & S_IFMT) == S_IFLNK)) { + /* + * If the file is a symbolic link, we remember that + * and then we get the status for the refd file. + */ + target->stat.is_sym_link = true; + result = stat_vroot(target->string_mb, &buf, NULL, VROOT_DEFAULT); + } else { + target->stat.is_sym_link = false; + } + + if (result < 0) { + target->stat.time = file_doesnt_exist; + target->stat.stat_errno = errno; + if ((errno == ENOENT) && + vpath_defined && +/* azv, fixing bug 1262942, VPATH works with a leaf name + * but not a directory name. + */ + (target->string_mb[0] != (int) slash_char) ) { +/* BID_1214655 */ +/* azv */ + vpath_exists(target); + // return vpath_exists(target); + } + } else { + /* Save all the information we need about the file */ + target->stat.stat_errno = 0; + target->stat.is_file = true; + target->stat.mode = buf.st_mode & 0777; + target->stat.size = buf.st_size; + target->stat.is_dir = + BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR); + if (target->stat.is_dir) { + target->stat.time = file_is_dir; + } else { + /* target->stat.time = buf.st_mtime; */ +/* BID_1129806 */ +/* vis@nbsp.nsk.su */ +#if defined(linux) + timestruc_t ttime = { buf.st_mtime, 0 }; + target->stat.time = MAX(ttime, file_min_time); +#else + target->stat.time = MAX(buf.st_mtim, file_min_time); +#endif + } + } + if ((target->colon_splits > 0) && + (get_prop(target->prop, time_prop) == NULL)) { + append_prop(target, time_prop)->body.time.time = + target->stat.time; + } + return target->stat.time; +} + +/* + * set_target_stat( target, buf) + * + * Called by exists() to set some stat fields in the Name structure + * to those read by the stat_vroot() call (from disk). + * + * Parameters: + * target The target whose stat field is set + * buf stat values (on disk) of the file + * represented by target. + */ +void +set_target_stat(register Name target, struct stat buf) +{ + target->stat.stat_errno = 0; + target->stat.is_file = true; + target->stat.mode = buf.st_mode & 0777; + target->stat.size = buf.st_size; + target->stat.is_dir = + BOOLEAN((buf.st_mode & S_IFMT) == S_IFDIR); + if (target->stat.is_dir) { + target->stat.time = file_is_dir; + } else { + /* target->stat.time = buf.st_mtime; */ +/* BID_1129806 */ +/* vis@nbsp.nsk.su */ +#if defined(linux) + timestruc_t ttime = { buf.st_mtime, 0 }; + target->stat.time = ttime; +#else + target->stat.time = MAX(buf.st_mtim, file_min_time); +#endif + } +} + + +/* + * vpath_exists(target) + * + * Called if exists() discovers that there is a VPATH defined. + * This function stats the VPATH translation of the target. + * + * Return value: + * The time the target was created + * + * Parameters: + * target The target to check + * + * Global variables used: + * vpath_name The Name "VPATH", used to get macro value + */ +static timestruc_t& +vpath_exists(register Name target) +{ + wchar_t *vpath; + wchar_t file_name[MAXPATHLEN]; + wchar_t *name_p; + Name alias; + + /* + * To avoid recursive search through VPATH when exists(alias) is called + */ + vpath_defined = false; + + Wstring wcb(getvar(vpath_name)); + Wstring wcb1(target); + + vpath = wcb.get_string(); + + while (*vpath != (int) nul_char) { + name_p = file_name; + while ((*vpath != (int) colon_char) && + (*vpath != (int) nul_char)) { + *name_p++ = *vpath++; + } + *name_p++ = (int) slash_char; + (void) wscpy(name_p, wcb1.get_string()); + alias = GETNAME(file_name, FIND_LENGTH); + if (exists(alias) != file_doesnt_exist) { + target->stat.is_file = true; + target->stat.mode = alias->stat.mode; + target->stat.size = alias->stat.size; + target->stat.is_dir = alias->stat.is_dir; + target->stat.time = alias->stat.time; + maybe_append_prop(target, vpath_alias_prop)-> + body.vpath_alias.alias = alias; + target->has_vpath_alias_prop = true; + vpath_defined = true; + return alias->stat.time; + } + while ((*vpath != (int) nul_char) && + ((*vpath == (int) colon_char) || iswspace(*vpath))) { + vpath++; + } + } + /* + * Restore vpath_defined + */ + vpath_defined = true; + return target->stat.time; +} + +/* + * read_dir(dir, pattern, line, library) + * + * Used to enter the contents of directories into makes namespace. + * Presence of a file is important when scanning for implicit rules. + * read_dir() is also used to expand wildcards in dependency lists. + * + * Return value: + * Non-0 if we found files to match the pattern + * + * Parameters: + * dir Path to the directory to read + * pattern Pattern for that files should match or NULL + * line When we scan using a pattern we enter files + * we find as dependencies for this line + * library If we scan for "lib.a(<wildcard-member>)" + * + * Global variables used: + * debug_level Should we trace the dir reading? + * dot The Name ".", compared against + * sccs_dir_path The path to the SCCS dir (from PROJECTDIR) + * vpath_defined Was the variable VPATH defined in environment? + * vpath_name The Name "VPATH", use to get macro value + */ +int +read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library) +{ + wchar_t file_name[MAXPATHLEN]; + wchar_t *file_name_p = file_name; + Name file; + wchar_t plain_file_name[MAXPATHLEN]; + wchar_t *plain_file_name_p; + Name plain_file; + wchar_t tmp_wcs_buffer[MAXPATHLEN]; + DIR *dir_fd; + int m_local_dependency=0; +#if defined(SUN5_0) || defined(HP_UX) +#define d_fileno d_ino + register struct dirent *dp; +#else + register struct direct *dp; +#endif + wchar_t *vpath = NULL; + wchar_t *p; + int result = 0; + + if(dir->hash.length >= MAXPATHLEN) { + return 0; + } + + Wstring wcb(dir); + Wstring vps; + + /* A directory is only read once unless we need to expand wildcards. */ + if (pattern == NULL) { + if (dir->has_read_dir) { + return 0; + } + dir->has_read_dir = true; + } + /* Check if VPATH is active and setup list if it is. */ + if (vpath_defined && (dir == dot)) { + vps.init(getvar(vpath_name)); + vpath = vps.get_string(); + } + + /* + * Prepare the string where we build the full name of the + * files in the directory. + */ + if ((dir->hash.length > 1) || (wcb.get_string()[0] != (int) period_char)) { + (void) wscpy(file_name, wcb.get_string()); + MBSTOWCS(wcs_buffer, "/"); + (void) wscat(file_name, wcs_buffer); + file_name_p = file_name + wslen(file_name); + } + + /* Open the directory. */ +vpath_loop: + dir_fd = opendir(dir->string_mb); + if (dir_fd == NULL) { + return 0; + } + + /* Read all the directory entries. */ + while ((dp = readdir(dir_fd)) != NULL) { + /* We ignore "." and ".." */ + if ((dp->d_fileno == 0) || + ((dp->d_name[0] == (int) period_char) && + ((dp->d_name[1] == 0) || + ((dp->d_name[1] == (int) period_char) && + (dp->d_name[2] == 0))))) { + continue; + } + /* + * Build the full name of the file using whatever + * path supplied to the function. + */ + MBSTOWCS(tmp_wcs_buffer, dp->d_name); + (void) wscpy(file_name_p, tmp_wcs_buffer); + file = enter_file_name(file_name, library); + if ((pattern != NULL) && amatch(tmp_wcs_buffer, pattern)) { + /* + * If we are expanding a wildcard pattern, we + * enter the file as a dependency for the target. + */ + if (debug_level > 0){ + WCSTOMBS(mbs_buffer, pattern); + (void) printf(catgets(catd, 1, 231, "'%s: %s' due to %s expansion\n"), + line->body.line.target->string_mb, + file->string_mb, + mbs_buffer); + } + enter_dependency(line, file, false); + result++; + } else { + /* + * If the file has an SCCS/s. file, + * we will detect that later on. + */ + file->stat.has_sccs = NO_SCCS; + /* + * If this is an s. file, we also enter it as if it + * existed in the plain directory. + */ + if ((dp->d_name[0] == 's') && + (dp->d_name[1] == (int) period_char)) { + + MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2); + plain_file_name_p = plain_file_name; + (void) wscpy(plain_file_name_p, tmp_wcs_buffer); + plain_file = GETNAME(plain_file_name, FIND_LENGTH); + plain_file->stat.is_file = true; + plain_file->stat.has_sccs = HAS_SCCS; + /* + * Enter the s. file as a dependency for the + * plain file. + */ + maybe_append_prop(plain_file, sccs_prop)-> + body.sccs.file = file; + MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2); + if ((pattern != NULL) && + amatch(tmp_wcs_buffer, pattern)) { + if (debug_level > 0) { + WCSTOMBS(mbs_buffer, pattern); + (void) printf(catgets(catd, 1, 232, "'%s: %s' due to %s expansion\n"), + line->body.line.target-> + string_mb, + plain_file->string_mb, + mbs_buffer); + } + enter_dependency(line, plain_file, false); + result++; + } + } + } + } + (void) closedir(dir_fd); + if ((vpath != NULL) && (*vpath != (int) nul_char)) { + while ((*vpath != (int) nul_char) && + (iswspace(*vpath) || (*vpath == (int) colon_char))) { + vpath++; + } + p = vpath; + while ((*vpath != (int) colon_char) && + (*vpath != (int) nul_char)) { + vpath++; + } + if (vpath > p) { + dir = GETNAME(p, vpath - p); + goto vpath_loop; + } + } +/* + * look into SCCS directory only if it's not svr4. For svr4 dont do that. + */ + +/* + * Now read the SCCS directory. + * Files in the SCSC directory are considered to be part of the set of + * files in the plain directory. They are also entered in their own right. + * Prepare the string where we build the true name of the SCCS files. + */ + (void) wsncpy(plain_file_name, + file_name, + file_name_p - file_name); + plain_file_name[file_name_p - file_name] = 0; + plain_file_name_p = plain_file_name + wslen(plain_file_name); + + if(!svr4) { + + if (sccs_dir_path != NULL) { + wchar_t tmp_wchar; + wchar_t path[MAXPATHLEN]; + char mb_path[MAXPATHLEN]; + + if (file_name_p - file_name > 0) { + tmp_wchar = *file_name_p; + *file_name_p = 0; + WCSTOMBS(mbs_buffer, file_name); + (void) sprintf(mb_path, NOCATGETS("%s/%s/SCCS"), + sccs_dir_path, + mbs_buffer); + *file_name_p = tmp_wchar; + } else { + (void) sprintf(mb_path, NOCATGETS("%s/SCCS"), sccs_dir_path); + } + MBSTOWCS(path, mb_path); + (void) wscpy(file_name, path); + } else { + MBSTOWCS(wcs_buffer, NOCATGETS("SCCS")); + (void) wscpy(file_name_p, wcs_buffer); + } + } else { + MBSTOWCS(wcs_buffer, NOCATGETS(".")); + (void) wscpy(file_name_p, wcs_buffer); + } + /* Internalize the constructed SCCS dir name. */ + (void) exists(dir = GETNAME(file_name, FIND_LENGTH)); + /* Just give up if the directory file doesnt exist. */ + if (!dir->stat.is_file) { + return result; + } + /* Open the directory. */ + dir_fd = opendir(dir->string_mb); + if (dir_fd == NULL) { + return result; + } + MBSTOWCS(wcs_buffer, "/"); + (void) wscat(file_name, wcs_buffer); + file_name_p = file_name + wslen(file_name); + + while ((dp = readdir(dir_fd)) != NULL) { + if ((dp->d_fileno == 0) || + ((dp->d_name[0] == (int) period_char) && + ((dp->d_name[1] == 0) || + ((dp->d_name[1] == (int) period_char) && + (dp->d_name[2] == 0))))) { + continue; + } + /* Construct and internalize the true name of the SCCS file. */ + MBSTOWCS(wcs_buffer, dp->d_name); + (void) wscpy(file_name_p, wcs_buffer); + file = GETNAME(file_name, FIND_LENGTH); + file->stat.is_file = true; + file->stat.has_sccs = NO_SCCS; + /* + * If this is an s. file, we also enter it as if it + * existed in the plain directory. + */ + if ((dp->d_name[0] == 's') && + (dp->d_name[1] == (int) period_char)) { + + MBSTOWCS(wcs_buffer, dp->d_name + 2); + (void) wscpy(plain_file_name_p, wcs_buffer); + plain_file = GETNAME(plain_file_name, FIND_LENGTH); + plain_file->stat.is_file = true; + plain_file->stat.has_sccs = HAS_SCCS; + /* if sccs dependency is already set,skip */ + if(plain_file->prop) { + Property sprop = get_prop(plain_file->prop,sccs_prop); + if(sprop != NULL) { + if (sprop->body.sccs.file) { + goto try_pattern; + } + } + } + + /* + * Enter the s. file as a dependency for the + * plain file. + */ + maybe_append_prop(plain_file, sccs_prop)-> + body.sccs.file = file; +try_pattern: + MBSTOWCS(tmp_wcs_buffer, dp->d_name + 2); + if ((pattern != NULL) && + amatch(tmp_wcs_buffer, pattern)) { + if (debug_level > 0) { + WCSTOMBS(mbs_buffer, pattern); + (void) printf(catgets(catd, 1, 233, "'%s: %s' due to %s expansion\n"), + line->body.line.target-> + string_mb, + plain_file->string_mb, + mbs_buffer); + } + enter_dependency(line, plain_file, false); + result++; + } + } + } + (void) closedir(dir_fd); + + return result; +} + +/* + * enter_file_name(name_string, library) + * + * Helper function for read_dir(). + * + * Return value: + * The Name that was entered + * + * Parameters: + * name_string Name of the file we want to enter + * library The library it is a member of, if any + * + * Global variables used: + */ +static Name +enter_file_name(wchar_t *name_string, wchar_t *library) +{ + wchar_t buffer[STRING_BUFFER_LENGTH]; + String_rec lib_name; + Name name; + Property prop; + + if (library == NULL) { + name = GETNAME(name_string, FIND_LENGTH); + name->stat.is_file = true; + return name; + } + + INIT_STRING_FROM_STACK(lib_name, buffer); + append_string(library, &lib_name, FIND_LENGTH); + append_char((int) parenleft_char, &lib_name); + append_string(name_string, &lib_name, FIND_LENGTH); + append_char((int) parenright_char, &lib_name); + + name = GETNAME(lib_name.buffer.start, FIND_LENGTH); + name->stat.is_file = true; + name->is_member = true; + prop = maybe_append_prop(name, member_prop); + prop->body.member.library = GETNAME(library, FIND_LENGTH); + prop->body.member.library->stat.is_file = true; + prop->body.member.entry = NULL; + prop->body.member.member = GETNAME(name_string, FIND_LENGTH); + prop->body.member.member->stat.is_file = true; + return name; +} + +/* + * star_match(string, pattern) + * + * This is a regular shell type wildcard pattern matcher + * It is used when xpanding wildcards in dependency lists + * + * Return value: + * Indication if the string matched the pattern + * + * Parameters: + * string String to match + * pattern Pattern to match it against + * + * Global variables used: + */ +static Boolean +star_match(register wchar_t *string, register wchar_t *pattern) +{ + register int pattern_ch; + + switch (*pattern) { + case 0: + return succeeded; + case bracketleft_char: + case question_char: + case asterisk_char: + while (*string) { + if (amatch(string++, pattern)) { + return succeeded; + } + } + break; + default: + pattern_ch = (int) *pattern++; + while (*string) { + if ((*string++ == pattern_ch) && + amatch(string, pattern)) { + return succeeded; + } + } + break; + } + return failed; +} + +/* + * amatch(string, pattern) + * + * Helper function for shell pattern matching + * + * Return value: + * Indication if the string matched the pattern + * + * Parameters: + * string String to match + * pattern Pattern to match it against + * + * Global variables used: + */ +static Boolean +amatch(register wchar_t *string, register wchar_t *pattern) +{ + register long lower_bound; + register long string_ch; + register long pattern_ch; + register int k; + +top: + for (; 1; pattern++, string++) { + lower_bound = 017777777777; + string_ch = *string; + switch (pattern_ch = *pattern) { + case bracketleft_char: + k = 0; + while ((pattern_ch = *++pattern) != 0) { + switch (pattern_ch) { + case bracketright_char: + if (!k) { + return failed; + } + string++; + pattern++; + goto top; + case hyphen_char: + k |= (lower_bound <= string_ch) && + (string_ch <= + (pattern_ch = pattern[1])); + default: + if (string_ch == + (lower_bound = pattern_ch)) { + k++; + } + } + } + return failed; + case asterisk_char: + return star_match(string, ++pattern); + case 0: + return BOOLEAN(!string_ch); + case question_char: + if (string_ch == 0) { + return failed; + } + break; + default: + if (pattern_ch != string_ch) { + return failed; + } + break; + } + } + /* NOTREACHED */ +} + diff --git a/usr/src/make_src/Make/bin/make/common/globals.cc b/usr/src/make_src/Make/bin/make/common/globals.cc new file mode 100644 index 0000000..903a109 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/globals.cc @@ -0,0 +1,217 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)globals.cc 1.42 06/12/12 + */ + +#pragma ident "@(#)globals.cc 1.42 06/12/12" + +/* + * globals.cc + * + * This declares all global variables + */ + +/* + * Included files + */ +#include <nl_types.h> +#include <mk/defs.h> +#include <sys/stat.h> + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Global variables used by make only + */ + FILE *dependency_report_file; + +/* + * Global variables used by make + */ + Boolean allrules_read=false; + Name posix_name; + Name svr4_name; + Boolean sdot_target; /* used to identify s.m(/M)akefile */ + Boolean all_parallel; /* TEAMWARE_MAKE_CMN */ + Boolean assign_done; + int foo; + Boolean build_failed_seen; +#ifdef DISTRIBUTED + Boolean building_serial; +#endif + Name built_last_make_run; + Name c_at; +#ifdef DISTRIBUTED + Boolean called_make = false; +#endif + Boolean cleanup; + Boolean close_report; + Boolean command_changed; + Boolean commands_done; + Chain conditional_targets; + Name conditionals; + Boolean continue_after_error; /* `-k' */ + Property current_line; + Name current_make_version; + Name current_target; + short debug_level; + Cmd_line default_rule; + Name default_rule_name; + Name default_target_to_build; + Name dmake_group; + Name dmake_max_jobs; + Name dmake_mode; + DMake_mode dmake_mode_type; + Name dmake_output_mode; + DMake_output_mode output_mode = txt1_mode; + Name dmake_odir; + Name dmake_rcfile; + Name done; + Name dot; + Name dot_keep_state; + Name dot_keep_state_file; + Name empty_name; +#if defined(HP_UX) || defined(linux) + int exit_status; +#endif + Boolean fatal_in_progress; + int file_number; +#if 0 + Boolean filter_stderr; /* `-X' */ +#endif + Name force; + Name ignore_name; + Boolean ignore_errors; /* `-i' */ + Boolean ignore_errors_all; /* `-i' */ + Name init; + int job_msg_id; + Boolean keep_state; + Name make_state; +#ifdef TEAMWARE_MAKE_CMN + timestruc_t make_state_before; +#endif + Dependency makefiles_used; + Name makeflags; +// Boolean make_state_locked; // Moved to lib/mksh + Name make_version; + char mbs_buffer2[(MAXPATHLEN * MB_LEN_MAX)]; + char *mbs_ptr; + char *mbs_ptr2; + int mtool_msgs_fd; + Boolean depinfo_already_read = false; +#ifdef NSE + Name derived_src; + Boolean nse; /* NSE on */ + Name nse_backquote_seen; + char nse_depinfo_lockfile[MAXPATHLEN]; + Boolean nse_depinfo_locked; + Boolean nse_did_recursion; + Name nse_shell_var_used; + Boolean nse_watch_vars = false; + wchar_t current_makefile[MAXPATHLEN]; +#endif + Boolean no_action_was_taken = true; /* true if we've not ** + ** run any command */ + + Boolean no_parallel = false; /* TEAMWARE_MAKE_CMN */ +#ifdef SGE_SUPPORT + Boolean grid = false; /* TEAMWARE_MAKE_CMN */ +#endif + Name no_parallel_name; + Name not_auto; + Boolean only_parallel; /* TEAMWARE_MAKE_CMN */ + Boolean parallel; /* TEAMWARE_MAKE_CMN */ + Name parallel_name; + Name localhost_name; + int parallel_process_cnt; + Percent percent_list; + Dyntarget dyntarget_list; + Name plus; + Name pmake_machinesfile; + Name precious; + Name primary_makefile; + Boolean quest; /* `-q' */ + short read_trace_level; + Boolean reading_dependencies = false; + Name recursive_name; + int recursion_level; + short report_dependencies_level = 0; /* -P */ + Boolean report_pwd; + Boolean rewrite_statefile; + Running running_list; + char *sccs_dir_path; + Name sccs_get_name; + Name sccs_get_posix_name; + Cmd_line sccs_get_rule; + Cmd_line sccs_get_org_rule; + Cmd_line sccs_get_posix_rule; + Name get_name; + Cmd_line get_rule; + Name get_posix_name; + Cmd_line get_posix_rule; + Boolean send_mtool_msgs; /* `-K' */ + Boolean all_precious; + Boolean silent_all; /* `-s' */ + Boolean report_cwd; /* `-w' */ + Boolean silent; /* `-s' */ + Name silent_name; + char *stderr_file = NULL; + char *stdout_file = NULL; +#ifdef SGE_SUPPORT + char script_file[MAXPATHLEN] = ""; +#endif + Boolean stdout_stderr_same; + Dependency suffixes; + Name suffixes_name; + Name sunpro_dependencies; + Boolean target_variants; + char *tmpdir = NOCATGETS("/tmp"); + char *temp_file_directory = NOCATGETS("."); + Name temp_file_name; + short temp_file_number; + time_t timing_start; + wchar_t *top_level_target; + Boolean touch; /* `-t' */ + Boolean trace_reader; /* `-D' */ + Boolean build_unconditional; /* `-u' */ + pathpt vroot_path = VROOT_DEFAULT; + Name wait_name; + wchar_t wcs_buffer2[MAXPATHLEN]; + wchar_t *wcs_ptr; + wchar_t *wcs_ptr2; + nl_catd catd; + long int hostid; + +/* + * File table of contents + */ + diff --git a/usr/src/make_src/Make/bin/make/common/implicit.cc b/usr/src/make_src/Make/bin/make/common/implicit.cc new file mode 100644 index 0000000..a9b2f1d --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/implicit.cc @@ -0,0 +1,1479 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)implicit.cc 1.64 06/12/12 + */ + +#pragma ident "@(#)implicit.cc 1.64 06/12/12" + +/* + * implicit.c + * + * Handle suffix and percent rules + */ + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/macro.h> /* expand_value() */ +#include <mksh/misc.h> /* retmem() */ + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +static wchar_t WIDE_NULL[1] = {(wchar_t) nul_char}; + +/* + * File table of contents + */ +extern Doname find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking); +extern Doname find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking); +extern Doname find_double_suffix_rule(register Name target, Property *command, Boolean rechecking); +extern void build_suffix_list(register Name target_suffix); +extern Doname find_percent_rule(register Name target, Property *command, Boolean rechecking); +static void create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent); +static Boolean match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf); +static void construct_string_from_pattern(Percent pat_rule, String percent, String result); +static Boolean dependency_exists(Name target, Property line); +extern Property maybe_append_prop(Name, Property_id); +extern void add_target_to_chain(Name target, Chain * query); + +/* + * find_suffix_rule(target, target_body, target_suffix, command, rechecking) + * + * Does the lookup for single and double suffix rules. + * It calls build_suffix_list() to build the list of possible suffixes + * for the given target. + * It then scans the list to find the first possible source file that + * exists. This is done by concatenating the body of the target name + * (target name less target suffix) and the source suffix and checking + * if the resulting file exists. + * + * Return value: + * Indicates if search failed or not + * + * Parameters: + * target The target we need a rule for + * target_body The target name without the suffix + * target_suffix The suffix of the target + * command Pointer to slot to deposit cmd in if found + * rechecking true if we are rechecking target which depends + * on conditional macro and keep_state is set + * + * Global variables used: + * debug_level Indicates how much tracing to do + * recursion_level Used for tracing + */ + +extern int printf (const char *, ...); + +static Boolean actual_doname = false; + +/* /tolik/ + * fix bug 1247448: Suffix Rules failed when combine with Pattern Matching Rules. + * When make attemps to apply % rule it didn't look for a single suffix rule because + * if "doname" is called from "find_percent_rule" argument "implicit" is set to true + * and find_suffix_rule was not called. I've commented the checking of "implicit" + * in "doname" and make got infinite recursion for SVR4 tilde rules. + * Usage of "we_are_in_tilde" is intended to avoid this recursion. + */ + +static Boolean we_are_in_tilde = false; + +Doname +find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking) +{ + static wchar_t static_string_buf_3M [ 3 * MAXPATHLEN ]; + Name true_target = target; + wchar_t *sourcename = (wchar_t*)static_string_buf_3M; + register wchar_t *put_suffix; + register Property source_suffix; + register Name source; + Doname result; + register Property line; + extern Boolean tilde_rule; + Boolean name_found = true; + Boolean posix_tilde_attempt = true; + int src_len = MAXPATHLEN + strlen(target_body->string_mb); + + /* + * To avoid infinite recursion + */ + if(we_are_in_tilde) { + we_are_in_tilde = false; + return(build_dont_know); + } + + /* + * If the target is a constructed one for a "::" target, + * we need to consider that. + */ + if (target->has_target_prop) { + true_target = get_prop(target->prop, + target_prop)->body.target.target; + } + if (debug_level > 1) { + (void) printf(NOCATGETS("%*sfind_suffix_rule(%s,%s,%s)\n"), + recursion_level, + "", + true_target->string_mb, + target_body->string_mb, + target_suffix->string_mb); + } + if (command != NULL) { + if ((true_target->suffix_scan_done == true) && (*command == NULL)) { + return build_ok; + } + } + true_target->suffix_scan_done = true; + /* + * Enter all names from the directory where the target lives as + * files that makes sense. + * This will make finding the synthesized source possible. + */ + read_directory_of_file(target_body); + /* Cache the suffixes for this target suffix if not done. */ + if (!target_suffix->has_read_suffixes) { + build_suffix_list(target_suffix); + } + /* Preload the sourcename vector with the head of the target name. */ + if (src_len >= sizeof(static_string_buf_3M)) { + sourcename = ALLOC_WC(src_len); + } + (void) mbstowcs(sourcename, + target_body->string_mb, + (int) target_body->hash.length); + put_suffix = sourcename + target_body->hash.length; + /* Scan the suffix list for the target if one exists. */ + if (target_suffix->has_suffixes) { +posix_attempts: + for (source_suffix = get_prop(target_suffix->prop, + suffix_prop); + source_suffix != NULL; + source_suffix = get_prop(source_suffix->next, + suffix_prop)) { + /* Build the synthesized source name. */ + (void) mbstowcs(put_suffix, + source_suffix->body. + suffix.suffix->string_mb, + (int) source_suffix->body. + suffix.suffix->hash.length); + put_suffix[source_suffix->body. + suffix.suffix->hash.length] = + (int) nul_char; + if (debug_level > 1) { + WCSTOMBS(mbs_buffer, sourcename); + (void) printf(catgets(catd, 1, 218, "%*sTrying %s\n"), + recursion_level, + "", + mbs_buffer); + } + source = getname_fn(sourcename, FIND_LENGTH, false, &name_found); + /* + * If the source file is not registered as + * a file, this source suffix did not match. + */ + if(vpath_defined && !posix && !svr4) { + (void) exists(source); + } + if (!source->stat.is_file) { + if(!(posix|svr4)) + { + if(!name_found) { + free_name(source); + } + continue; + } + + /* following code will ensure that the corresponding + ** tilde rules are executed when corresponding s. file + ** exists in the current directory. Though the current + ** target ends with a ~ character, there wont be any + ** any file in the current directory with that suffix + ** as it's fictitious. Even if it exists, it'll + ** execute all the rules for the ~ target. + */ + + if(source->string_mb[source->hash.length - 1] == '~' && + ( svr4 || posix_tilde_attempt ) ) + { + char *p, *np; + char *tmpbuf; + + tmpbuf = getmem(source->hash.length + 8); + /* + 8 to add "s." or "SCCS/s." */ + memset(tmpbuf,0,source->hash.length + 8); + source->string_mb[source->hash.length - 1] = '\0'; + if(p = (char *) memchr((char *)source->string_mb,'/',source->hash.length)) + { + while(1) { + if(np = (char *) memchr((char *)p+1,'/',source->hash.length - (p - source->string_mb))) { + p = np; + } else {break;} + } + /* copy everything including '/' */ + strncpy(tmpbuf, source->string_mb, p - source->string_mb + 1); + strcat(tmpbuf, NOCATGETS("s.")); + strcat(tmpbuf, p+1); + retmem((wchar_t *) source->string_mb); + source->string_mb = tmpbuf; + + } else { + strcpy(tmpbuf, NOCATGETS("s.")); + strcat(tmpbuf, source->string_mb); + retmem((wchar_t *) source->string_mb); + source->string_mb = tmpbuf; + + } + source->hash.length = strlen(source->string_mb); + if(exists(source) == file_doesnt_exist) + continue; + tilde_rule = true; + we_are_in_tilde = true; + } else { + if(!name_found) { + free_name(source); + } + continue; + } + } else { + if(posix && posix_tilde_attempt) { + if(exists(source) == file_doesnt_exist) { + if(!name_found) { + free_name(source); + } + continue; + } + } + } + + if (command != NULL) { + if(!name_found) { + store_name(source); + } + /* + * The source file is a file. + * Make sure it is up to date. + */ + if (dependency_exists(source, + get_prop(target->prop, + line_prop))) { + result = (Doname) source->state; + } else { +#ifdef NSE + nse_check_derived_src(target, source->string, + source_suffix->body.suffix.command_template); +#endif +#if 0 /* with_squiggle sends false, which is buggy. : djay */ + result = doname(source, + (Boolean) source_suffix->body. + suffix.suffix->with_squiggle, + true); +#else + result = doname(source, + true, + true); +#endif + } + } else { + result = target_can_be_built(source); + + if (result == build_ok) { + return result; + } else { + if(!name_found) { + free_name(source); + } + continue; + } + } + + switch (result) { + case build_dont_know: + /* + * If we still can't build the source, + * this rule is not a match, + * try the next one. + */ + if (source->stat.time == file_doesnt_exist) { + if(!name_found) { + free_name(source); + } + continue; + } + case build_running: + if(!name_found) { + store_name(source); + } + true_target->suffix_scan_done = false; + line = maybe_append_prop(target, line_prop); + enter_dependency(line, source, false); + line->body.line.target = true_target; + return build_running; + case build_ok: + if(!name_found) { + store_name(source); + } + break; + case build_failed: + if(!name_found) { + store_name(source); + } + if (sourcename != static_string_buf_3M) { + retmem(sourcename); + } + return build_failed; + } + + if (debug_level > 1) { + WCSTOMBS(mbs_buffer, sourcename); + (void) printf(catgets(catd, 1, 219, "%*sFound %s\n"), + recursion_level, + "", + mbs_buffer); + } + + if (source->depends_on_conditional) { + target->depends_on_conditional = true; + } +/* + * Since it is possible that the same target is built several times during + * the make run, we have to patch the target with all information we found + * here. Thus, the target will have an explicit rule the next time around. + */ + line = maybe_append_prop(target, line_prop); + if (*command == NULL) { + *command = line; + } + if ((source->stat.time > (*command)->body.line.dependency_time) && + (debug_level > 1)) { + (void) printf(catgets(catd, 1, 220, "%*sDate(%s)=%s Date-dependencies(%s)=%s\n"), + recursion_level, + "", + source->string_mb, + time_to_string(source-> + stat.time), + true_target->string_mb, + time_to_string((*command)-> + body.line. + dependency_time)); + } + /* + * Determine if this new dependency made the + * target out of date. + */ + (*command)->body.line.dependency_time = + MAX((*command)->body.line.dependency_time, + source->stat.time); + Boolean out_of_date; + if (target->is_member) { + out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, + (*command)->body.line.dependency_time); + } else { + out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, + (*command)->body.line.dependency_time); + } + if (build_unconditional || out_of_date) { + if(!rechecking) { + line->body.line.is_out_of_date = true; + } + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 221, "%*sBuilding %s using suffix rule for %s%s because it is out of date relative to %s\n"), + recursion_level, + "", + true_target->string_mb, + source_suffix->body.suffix.suffix->string_mb, + target_suffix->string_mb, + source->string_mb); + } + } + /* + * Add the implicit rule as the target's explicit + * rule if none actually given, and register + * dependency. + * The time checking above really should be + * conditional on actual use of implicit rule + * as well. + */ + line->body.line.sccs_command = false; + if (line->body.line.command_template == NULL) { + line->body.line.command_template = + source_suffix->body.suffix.command_template; + } + enter_dependency(line, source, false); + line->body.line.target = true_target; + /* + * Also make sure the rule is built with + * $* and $< bound properly. + */ + line->body.line.star = target_body; + if(svr4|posix) { + char * p; + char tstr[256]; + extern Boolean dollarless_flag; + extern Name dollarless_value; + + if(tilde_rule) { + MBSTOWCS(wcs_buffer, NOCATGETS(source->string_mb)); + dollarless_value = GETNAME(wcs_buffer,FIND_LENGTH); + } + else { + dollarless_flag = false; + } + } + line->body.line.less = source; + line->body.line.percent = NULL; + add_target_to_chain(source, &(line->body.line.query)); + if (sourcename != static_string_buf_3M) { + retmem(sourcename); + } + return build_ok; + } + if(posix && posix_tilde_attempt) { + posix_tilde_attempt = false; + goto posix_attempts; + } + if ((command != NULL) && + ((*command) != NULL) && + ((*command)->body.line.star == NULL)) { + (*command)->body.line.star = target_body; + } + } + if (sourcename != static_string_buf_3M) { + retmem(sourcename); + } + /* Return here in case no rule matched the target */ + return build_dont_know; +} + +/* + * find_ar_suffix_rule(target, true_target, command, rechecking) + * + * Scans the .SUFFIXES list and tries + * to find a suffix on it that matches the tail of the target member name. + * If it finds a matching suffix it calls find_suffix_rule() to find + * a rule for the target using the suffix ".a". + * + * Return value: + * Indicates if search failed or not + * + * Parameters: + * target The target we need a rule for + * true_target The proper name + * command Pointer to slot where we stuff cmd, if found + * rechecking true if we are rechecking target which depends + * on conditional macro and keep_state is set + * + * Global variables used: + * debug_level Indicates how much tracing to do + * dot_a The Name ".a", compared against + * recursion_level Used for tracing + * suffixes List of suffixes used for scan (from .SUFFIXES) + */ +Doname +find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking) +{ + wchar_t *target_end; + register Dependency suffix; + register int suffix_length; + Property line; + Name body; + static Name dot_a; + + Wstring targ_string(true_target); + Wstring suf_string; + + if (dot_a == NULL) { + MBSTOWCS(wcs_buffer, NOCATGETS(".a")); + dot_a = GETNAME(wcs_buffer, FIND_LENGTH); + } + target_end = targ_string.get_string() + true_target->hash.length; + + /* + * We compare the tail of the target name with the suffixes + * from .SUFFIXES. + */ + if (debug_level > 1) { + (void) printf(NOCATGETS("%*sfind_ar_suffix_rule(%s)\n"), + recursion_level, + "", + true_target->string_mb); + } + /* + * Scan the .SUFFIXES list to see if the target matches any of + * those suffixes. + */ + for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { + /* Compare one suffix. */ + suffix_length = suffix->name->hash.length; + suf_string.init(suffix->name); + if (!IS_WEQUALN(suf_string.get_string(), + target_end - suffix_length, + suffix_length)) { + goto not_this_one; + } + /* + * The target tail matched a suffix from the .SUFFIXES list. + * Now check for a rule to match. + */ + target->suffix_scan_done = false; + body = GETNAME(targ_string.get_string(), + (int)(true_target->hash.length - + suffix_length)); + we_are_in_tilde = false; + switch (find_suffix_rule(target, + body, + dot_a, + command, + rechecking)) { + case build_ok: + line = get_prop(target->prop, line_prop); + line->body.line.star = body; + return build_ok; + case build_running: + return build_running; + } + /* + * If no rule was found, we try the next suffix to see + * if it matches the target tail, and so on. + * Go here if the suffix did not match the target tail. + */ + not_this_one:; + } + return build_dont_know; +} + +/* + * find_double_suffix_rule(target, command, rechecking) + * + * Scans the .SUFFIXES list and tries + * to find a suffix on it that matches the tail of the target name. + * If it finds a matching suffix it calls find_suffix_rule() to find + * a rule for the target. + * + * Return value: + * Indicates if scan failed or not + * + * Parameters: + * target Target we need a rule for + * command Pointer to slot where we stuff cmd, if found + * rechecking true if we are rechecking target which depends + * on conditional macro and keep_state is set + * + * Global variables used: + * debug_level Indicates how much tracing to do + * recursion_level Used for tracing + * suffixes List of suffixes used for scan (from .SUFFIXES) + */ +Doname +find_double_suffix_rule(register Name target, Property *command, Boolean rechecking) +{ + Name true_target = target; + Name target_body; + register wchar_t *target_end; + register Dependency suffix; + register int suffix_length; + Boolean scanned_once = false; + Boolean name_found = true; + + Wstring targ_string; + Wstring suf_string; + + /* + * If the target is a constructed one for a "::" target, + * we need to consider that. + */ + if (target->has_target_prop) { + true_target = get_prop(target->prop, + target_prop)->body.target.target; + } + targ_string.init(true_target); + + /* + * We compare the tail of the target name with the + * suffixes from .SUFFIXES. + */ + target_end = targ_string.get_string() + true_target->hash.length; + if (debug_level > 1) { + (void) printf(NOCATGETS("%*sfind_double_suffix_rule(%s)\n"), + recursion_level, + "", + true_target->string_mb); + } + /* + * Scan the .SUFFIXES list to see if the target matches + * any of those suffixes. + */ + for (suffix = suffixes; suffix != NULL; suffix = suffix->next) { + target->suffix_scan_done = false; + true_target->suffix_scan_done = false; + /* Compare one suffix. */ + suffix_length = suffix->name->hash.length; + suf_string.init(suffix->name); + /* Check the lengths, or else RTC will report rua. */ + if (true_target->hash.length < suffix_length) { + goto not_this_one; + } else if (!IS_WEQUALN(suf_string.get_string(), + (target_end - suffix_length), + suffix_length)) { + goto not_this_one; + } + /* + * The target tail matched a suffix from the .SUFFIXES list. + * Now check for a rule to match. + */ + we_are_in_tilde = false; + target_body = GETNAME( + targ_string.get_string(), + (int)(true_target->hash.length - suffix_length) + ); + switch (find_suffix_rule(target, + target_body, + suffix->name, + command, + rechecking)) { + case build_ok: + return build_ok; + case build_running: + return build_running; + } + if (true_target->suffix_scan_done == true) { + scanned_once = true; + } + /* + * If no rule was found, we try the next suffix to see + * if it matches the target tail. And so on. + * Go here if the suffix did not match the target tail. + */ + not_this_one:; + } + if (scanned_once) + true_target->suffix_scan_done = true; + return build_dont_know; +} + +/* + * build_suffix_list(target_suffix) + * + * Scans the .SUFFIXES list and figures out + * which suffixes this target can be derived from. + * The target itself is not know here, we just know the suffix of the + * target. For each suffix on the list the target can be derived iff + * a rule exists for the name "<suffix-on-list><target-suffix>". + * A list of all possible building suffixes is built, with the rule for + * each, and tacked to the target suffix nameblock. + * + * Parameters: + * target_suffix The suffix we build a match list for + * + * Global variables used: + * debug_level Indicates how much tracing to do + * recursion_level Used for tracing + * suffixes List of suffixes used for scan (from .SUFFIXES) + * working_on_targets Indicates that this is a real target + */ +void +build_suffix_list(register Name target_suffix) +{ + register Dependency source_suffix; + wchar_t rule_name[MAXPATHLEN]; + register Property line; + register Property suffix; + Name rule; + + /* If this is before default.mk has been read we just return to try */ + /* again later */ + if ((suffixes == NULL) || !working_on_targets) { + return; + } + if (debug_level > 1) { + (void) printf(NOCATGETS("%*sbuild_suffix_list(%s) "), + recursion_level, + "", + target_suffix->string_mb); + } + /* Mark the target suffix saying we cashed its list */ + target_suffix->has_read_suffixes = true; + /* Scan the .SUFFIXES list */ + for (source_suffix = suffixes; + source_suffix != NULL; + source_suffix = source_suffix->next) { + /* + * Build the name "<suffix-on-list><target-suffix>". + * (a popular one would be ".c.o"). + */ + (void) mbstowcs(rule_name, + source_suffix->name->string_mb, + (int) source_suffix->name->hash.length); + (void) mbstowcs(rule_name + source_suffix->name->hash.length, + target_suffix->string_mb, + (int) target_suffix->hash.length); + /* + * Check if that name has a rule. If not, it cannot match + * any implicit rule scan and is ignored. + * The GETNAME() call only checks for presence, it will not + * enter the name if it is not defined. + */ + if (((rule = getname_fn(rule_name, + (int) (source_suffix->name-> + hash.length + + target_suffix->hash.length), + true)) != NULL) && + ((line = get_prop(rule->prop, line_prop)) != NULL)) { + if (debug_level > 1) { + (void) printf("%s ", rule->string_mb); + } + /* + * This makes it possible to quickly determine if + * it will pay to look for a suffix property. + */ + target_suffix->has_suffixes = true; + /* + * Add the suffix property to the target suffix + * and save the rule with it. + * All information the implicit rule scanner need + * is saved in the suffix property. + */ + suffix = append_prop(target_suffix, suffix_prop); + suffix->body.suffix.suffix = source_suffix->name; + suffix->body.suffix.command_template = + line->body.line.command_template; + } + } + if (debug_level > 1) { + (void) printf("\n"); + } +} + +/* + * find_percent_rule(target, command, rechecking) + * + * Tries to find a rule from the list of wildcard matched rules. + * It scans the list attempting to match the target. + * For each target match it checks if the corresponding source exists. + * If it does the match is returned. + * The percent_list is built at makefile read time. + * Each percent rule get one entry on the list. + * + * Return value: + * Indicates if the scan failed or not + * + * Parameters: + * target The target we need a rule for + * command Pointer to slot where we stuff cmd, if found + * rechecking true if we are rechecking target which depends + * on conditional macro and keep_state is set + * + * Global variables used: + * debug_level Indicates how much tracing to do + * percent_list List of all percent rules + * recursion_level Used for tracing + * empty_name + */ +Doname +find_percent_rule(register Name target, Property *command, Boolean rechecking) +{ + register Percent pat_rule, pat_depe; + register Name depe_to_check; + register Dependency depe; + register Property line; + String_rec string; + wchar_t string_buf[STRING_BUFFER_LENGTH]; + String_rec percent; + wchar_t percent_buf[STRING_BUFFER_LENGTH]; + Name true_target = target; + Name less; + Boolean nonpattern_less; + Boolean dep_name_found = false; + Doname result = build_dont_know; + Percent rule_candidate = NULL; + Boolean rule_maybe_ok; + Boolean is_pattern; + + /* If the target is constructed for a "::" target we consider that */ + if (target->has_target_prop) { + true_target = get_prop(target->prop, + target_prop)->body.target.target; + } + if (target->has_long_member_name) { + true_target = get_prop(target->prop, + long_member_name_prop)->body.long_member_name.member_name; + } + if (debug_level > 1) { + (void) printf(catgets(catd, 1, 222, "%*sLooking for %% rule for %s\n"), + recursion_level, + "", + true_target->string_mb); + } + for (pat_rule = percent_list; + pat_rule != NULL; + pat_rule = pat_rule->next) { + /* Avoid infinite recursion when expanding patterns */ + if (pat_rule->being_expanded == true) { + continue; + } + + /* Mark this pat_rule as "maybe ok". If no % rule is found + make will use this rule. The following algorithm is used: + 1) make scans all pattern rules in order to find the rule + where ALL dependencies, including nonpattern ones, exist or + can be built (GNU behaviour). If such rule is found make + will apply it. + 2) During this check make also remembers the first pattern rule + where all PATTERN dependencies can be build (no matter what + happens with nonpattern dependencies). + 3) If no rule satisfying 1) is found, make will apply the rule + remembered in 2) if there is one. + */ + rule_maybe_ok = true; + + /* used to track first percent dependency */ + less = NULL; + nonpattern_less = true; + + /* check whether pattern matches. + if it matches, percent string will contain matched percent part of pattern */ + if (!match_found_with_pattern(true_target, pat_rule, &percent, percent_buf)) { + continue; + } + if (pat_rule->dependencies != NULL) { + for (pat_depe = pat_rule->dependencies; + pat_depe != NULL; + pat_depe = pat_depe->next) { + /* checking result for dependency */ + result = build_dont_know; + + dep_name_found = true; + if (pat_depe->name->percent) { + is_pattern = true; + /* build dependency name */ + INIT_STRING_FROM_STACK(string, string_buf); + construct_string_from_pattern(pat_depe, &percent, &string); + depe_to_check = getname_fn(string.buffer.start, + FIND_LENGTH, + false, + &dep_name_found + ); + + if ((less == NULL) || nonpattern_less) { + less = depe_to_check; + nonpattern_less = false; + } + } else { + /* nonpattern dependency */ + is_pattern = false; + depe_to_check = pat_depe->name; + if(depe_to_check->dollar) { + INIT_STRING_FROM_STACK(string, string_buf); + expand_value(depe_to_check, &string, false); + depe_to_check = getname_fn(string.buffer.start, + FIND_LENGTH, + false, + &dep_name_found + ); + } + if (less == NULL) { + less = depe_to_check; + } + } + + if (depe_to_check == empty_name) { + result = build_ok; + } else { + if (debug_level > 1) { + (void) printf(catgets(catd, 1, 223, "%*sTrying %s\n"), + recursion_level, + "", + depe_to_check->string_mb); + } + + pat_rule->being_expanded = true; + + /* suppress message output */ + int save_debug_level = debug_level; + debug_level = 0; + + /* check whether dependency can be built */ + if (dependency_exists(depe_to_check, + get_prop(target->prop, + line_prop))) + { + result = (Doname) depe_to_check->state; + } else { + if(actual_doname) { + result = doname(depe_to_check, true, true); + } else { + result = target_can_be_built(depe_to_check); + } + if(!dep_name_found) { + if(result != build_ok && result != build_running) { + free_name(depe_to_check); + } else { + store_name(depe_to_check); + } + } + } + if(result != build_ok && is_pattern) { + rule_maybe_ok = false; + } + + /* restore debug_level */ + debug_level = save_debug_level; + } + + if (pat_depe->name->percent) { + if (string.free_after_use) { + retmem(string.buffer.start); + } + } + /* make can't figure out how to make this dependency */ + if (result != build_ok && result != build_running) { + pat_rule->being_expanded = false; + break; + } + } + } else { + result = build_ok; + } + + /* this pattern rule is the needed one since all dependencies could be built */ + if (result == build_ok || result == build_running) { + break; + } + + /* Make does not know how to build some of dependencies from this rule. + But if all "pattern" dependencies can be built, we remember this rule + as a candidate for the case if no other pattern rule found. + */ + if(rule_maybe_ok && rule_candidate == NULL) { + rule_candidate = pat_rule; + } + } + + /* if no pattern matching rule was found, use the remembered candidate + or return build_dont_know if there is no candidate. + */ + if (result != build_ok && result != build_running) { + if(rule_candidate) { + pat_rule = rule_candidate; + } else { + return build_dont_know; + } + } + + /* if we are performing only check whether dependency could be built with existing rules, + return success */ + if (command == NULL) { + if(pat_rule != NULL) { + pat_rule->being_expanded = false; + } + return result; + } + + if (debug_level > 1) { + (void) printf(catgets(catd, 1, 224, "%*sMatched %s:"), + recursion_level, + "", + target->string_mb); + + for (pat_depe = pat_rule->dependencies; + pat_depe != NULL; + pat_depe = pat_depe->next) { + if (pat_depe->name->percent) { + INIT_STRING_FROM_STACK(string, string_buf); + construct_string_from_pattern(pat_depe, &percent, &string); + depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH); + } else { + depe_to_check = pat_depe->name; + if(depe_to_check->dollar) { + INIT_STRING_FROM_STACK(string, string_buf); + expand_value(depe_to_check, &string, false); + depe_to_check = GETNAME(string.buffer.start, FIND_LENGTH); + } + } + + if (depe_to_check != empty_name) { + (void) printf(" %s", depe_to_check->string_mb); + } + } + + (void) printf(catgets(catd, 1, 225, " from: %s:"), + pat_rule->name->string_mb); + + for (pat_depe = pat_rule->dependencies; + pat_depe != NULL; + pat_depe = pat_depe->next) { + (void) printf(" %s", pat_depe->name->string_mb); + } + + (void) printf("\n"); + } + + if (true_target->colons == no_colon) { + true_target->colons = one_colon; + } + + /* create deppendency list and target group from matched pattern rule */ + create_target_group_and_dependencies_list(target, pat_rule, &percent); + + /* save command */ + line = get_prop(target->prop, line_prop); + *command = line; + + /* free query chain if one exist */ + while(line->body.line.query != NULL) { + Chain to_free = line->body.line.query; + line->body.line.query = line->body.line.query->next; + retmem_mb((char *) to_free); + } + + if (line->body.line.dependencies != NULL) { + /* build all collected dependencies */ + for (depe = line->body.line.dependencies; + depe != NULL; + depe = depe->next) { + actual_doname = true; + result = doname_check(depe->name, true, true, depe->automatic); + + actual_doname = false; + if (result == build_failed) { + pat_rule->being_expanded = false; + return build_failed; + } + if (result == build_running) { + pat_rule->being_expanded = false; + return build_running; + } + + if ((depe->name->stat.time > line->body.line.dependency_time) && + (debug_level > 1)) { + (void) printf(catgets(catd, 1, 226, "%*sDate(%s)=%s Date-dependencies(%s)=%s\n"), + recursion_level, + "", + depe->name->string_mb, + time_to_string(depe->name->stat.time), + true_target->string_mb, + time_to_string(line->body.line.dependency_time)); + } + + line->body.line.dependency_time = + MAX(line->body.line.dependency_time, depe->name->stat.time); + + /* determine whether this dependency made target out of date */ + Boolean out_of_date; + if (target->is_member || depe->name->is_member) { + out_of_date = (Boolean) OUT_OF_DATE_SEC(target->stat.time, depe->name->stat.time); + } else { + out_of_date = (Boolean) OUT_OF_DATE(target->stat.time, depe->name->stat.time); + } + if (build_unconditional || out_of_date) { + if(!rechecking) { + line->body.line.is_out_of_date = true; + } + add_target_to_chain(depe->name, &(line->body.line.query)); + + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 227, "%*sBuilding %s using pattern rule %s:"), + recursion_level, + "", + true_target->string_mb, + pat_rule->name->string_mb); + + for (pat_depe = pat_rule->dependencies; + pat_depe != NULL; + pat_depe = pat_depe->next) { + (void) printf(" %s", pat_depe->name->string_mb); + } + + (void) printf(catgets(catd, 1, 228, " because it is out of date relative to %s\n"), + depe->name->string_mb); + } + } + } + } else { + if ((true_target->stat.time <= file_doesnt_exist) || + (true_target->stat.time < line->body.line.dependency_time)) { + if(!rechecking) { + line->body.line.is_out_of_date = true; + } + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 229, "%*sBuilding %s using pattern rule %s: "), + recursion_level, + "", + true_target->string_mb, + pat_rule->name->string_mb, + (target->stat.time > file_doesnt_exist) ? + catgets(catd, 1, 230, "because it is out of date") : + catgets(catd, 1, 236, "because it does not exist")); + } + } + } + + /* enter explicit rule from percent rule */ + Name lmn_target = true_target; + if (true_target->has_long_member_name) { + lmn_target = get_prop(true_target->prop, long_member_name_prop)->body.long_member_name.member_name; + } + line->body.line.sccs_command = false; + line->body.line.target = true_target; + line->body.line.command_template = pat_rule->command_template; + line->body.line.star = GETNAME(percent.buffer.start, FIND_LENGTH); + line->body.line.less = less; + + if (lmn_target->parenleft) { + Wstring lmn_string(lmn_target); + + wchar_t *left = (wchar_t *) wschr(lmn_string.get_string(), (int) parenleft_char); + wchar_t *right = (wchar_t *) wschr(lmn_string.get_string(), (int) parenright_char); + + if ((left == NULL) || (right == NULL)) { + line->body.line.percent = NULL; + } else { + line->body.line.percent = GETNAME(left + 1, right - left - 1); + } + } else { + line->body.line.percent = NULL; + } + pat_rule->being_expanded = false; + +#ifdef TEAMWARE_MAKE_CMN + /* + * This #ifdef fixes a dmake bug, but introduces bugid 1136156. + */ + return result; +#else + return build_ok; +#endif +} + +/* + * match_found_with_pattern + * ( target, pat_rule, percent, percent_buf) + * + * matches "target->string" with a % pattern. + * If pattern contains a MACRO definition, it's expanded first. + * + * Return value: + * true if a match was found + * + * Parameters: + * target The target we're trying to match + * pattern + * percent record that contains "percent_buf" below + * percent_buf This is where the patched % part of pattern is stored + * + */ + +static Boolean +match_found_with_pattern(Name target, Percent pat_rule, String percent, wchar_t *percent_buf) { + String_rec string; + wchar_t string_buf[STRING_BUFFER_LENGTH]; + + /* construct prefix string and check whether prefix matches */ + Name prefix = pat_rule->patterns[0]; + int prefix_length; + + Wstring targ_string(target); + Wstring pref_string(prefix); + Wstring suf_string; + + if (prefix->dollar) { + INIT_STRING_FROM_STACK(string, string_buf); + expand_value(prefix, &string, false); + prefix_length = string.text.p - string.buffer.start; + if ((string.buffer.start[0] == (int) period_char) && + (string.buffer.start[1] == (int) slash_char)) { + string.buffer.start += 2; + prefix_length -= 2; + } + if (!targ_string.equaln(string.buffer.start, prefix_length)) { + return false; + } + } else { + prefix_length = prefix->hash.length; + if (!targ_string.equaln(&pref_string, prefix_length)) { + return false; + } + } + + /* do the same with pattern suffix */ + Name suffix = pat_rule->patterns[pat_rule->patterns_total - 1]; + suf_string.init(suffix); + + int suffix_length; + if (suffix->dollar) { + INIT_STRING_FROM_STACK(string, string_buf); + expand_value(suffix, &string, false); + suffix_length = string.text.p - string.buffer.start; + if(suffix_length > target->hash.length) { + return false; + } + if (!targ_string.equal(string.buffer.start, target->hash.length - suffix_length)) { + return false; + } + } else { + suffix_length = (int) suffix->hash.length; + if(suffix_length > target->hash.length) { + return false; + } + if (!targ_string.equal(&suf_string, target->hash.length - suffix_length)) { + return false; + } + } + + Boolean match_found = false; + int percent_length = target->hash.length - prefix_length - suffix_length; + + while (!match_found && (percent_length >= 0)) { + /* init result string */ + INIT_STRING_FROM_STACK(string, string_buf); + + /* init percent string */ + percent->buffer.start = percent_buf; + percent->text.p = percent_buf; + percent->text.end = NULL; + percent->free_after_use = false; + percent->buffer.end = percent_buf + STRING_BUFFER_LENGTH; + + /* construct percent and result strings */ + targ_string.append_to_str(percent, prefix_length, percent_length); + construct_string_from_pattern(pat_rule, percent, &string); + + /* check for match */ + if (targ_string.equal(string.buffer.start, 0)) { + match_found = true; + } else { + percent_length--; + } + } + + /* result */ + return match_found; +} + + +/* + * create_target_group_and_dependencies_list + * (target, pat_rule, percent) + * + * constructs dependency list and a target group from pattern. + * + * If we have the lines + * %/%.a + %/%.b + C%/CC%.c: yyy %.d bb%/BB%.e + * commands + * + * and we have matched the pattern xx/xx.a with %/%.a, then we + * construct a target group that looks like this: + * xx/xx.a + xx/xx.b + Cxx/CCxx.c: dependencies + * + * and construct dependency list that looks like this: + * yyy xx.d bbxx/BBxx.e + already existed dependencies + * + * Return value: + * none + * + * Parameters: + * target The target we are building, in the previous + * example, this is xx/xx.a + * pat_rule the % pattern that matched "target", here %/%.a + * percent string containing matched % part. In the example=xx. + * + * Global variables used: + * empty_name + */ + +static void +create_target_group_and_dependencies_list(Name target, Percent pat_rule, String percent) { + String_rec string; + wchar_t string_buf[STRING_BUFFER_LENGTH]; + Percent pat_depe; + Name depe; + Property line = maybe_append_prop(target, line_prop); + Chain new_target_group = NULL; + Chain *new_target_group_tail = &new_target_group; + Chain group_member; + + /* create and append dependencies from rule */ + for (pat_depe = pat_rule->dependencies; pat_depe != NULL; pat_depe = pat_depe->next) { + if (pat_depe->name->percent) { + INIT_STRING_FROM_STACK(string, string_buf); + construct_string_from_pattern(pat_depe, percent, &string); + depe = GETNAME(string.buffer.start, FIND_LENGTH); + if (depe != empty_name) { + enter_dependency(line, depe, false); + } + } else { + depe = pat_depe->name; + if(depe->dollar) { + INIT_STRING_FROM_STACK(string, string_buf); + expand_value(depe, &string, false); + depe = GETNAME(string.buffer.start, FIND_LENGTH); + } + enter_dependency(line, depe, false); + } + } + + /* if matched pattern is a group member, create new target group */ + for (group_member = pat_rule->target_group; group_member != NULL; group_member = group_member->next) { + Name new_target = group_member->name; + if (group_member->name->percent) { + INIT_STRING_FROM_STACK(string, string_buf); + construct_string_from_pattern(group_member->percent_member, percent, &string); + new_target = GETNAME(string.buffer.start, FIND_LENGTH); + if (new_target == empty_name) { + continue; + } + } + + /* check for duplicates */ + Chain tgm; + for (tgm = new_target_group; tgm != NULL; tgm = tgm->next) { + if (new_target == tgm->name) { + break; + } + } + if (tgm != NULL) { + continue; + } + + /* insert it into the targets list */ + (*new_target_group_tail) = ALLOC(Chain); + (*new_target_group_tail)->name = new_target; + (*new_target_group_tail)->next = NULL; + new_target_group_tail = &(*new_target_group_tail)->next; + } + + /* now we gathered all dependencies and created target group */ + line->body.line.target_group = new_target_group; + + /* update properties for group members */ + for (group_member = new_target_group; group_member != NULL; group_member = group_member->next) { + if (group_member->name != target) { + group_member->name->prop = target->prop; + group_member->name->conditional_cnt = target->conditional_cnt; + } + } +} + +/* + * construct_string_from_pattern + * (pat_rule, percent, result) + * + * after pattern matched a target this routine is called to construct targets and dependencies + * strings from this matched pattern rule and a string (percent) with substitutes % sign in pattern. + * + * Return value: + * none + * + * Parameters: + * pat_rule matched pattern rule + * percent string containing matched % sign part. + * result holds the result of string construction. + * + */ +static void +construct_string_from_pattern(Percent pat_rule, String percent, String result) { + for (int i = 0; i < pat_rule->patterns_total; i++) { + if (pat_rule->patterns[i]->dollar) { + expand_value(pat_rule->patterns[i], + result, + false); + + } else { + append_string(pat_rule->patterns[i]->string_mb, + result, + pat_rule->patterns[i]->hash.length); + } + + if (i < pat_rule->patterns_total - 1) { + append_string(percent->buffer.start, + result, + percent->text.p - percent->buffer.start); + } + } + + if ((result->buffer.start[0] == (int) period_char) && + (result->buffer.start[1] == (int) slash_char)) { + result->buffer.start += 2; + } +} + +/* + * dependency_exists(target, line) + * + * Returns true if the target exists in the + * dependency list of the line. + * + * Return value: + * True if target is on dependency list + * + * Parameters: + * target Target we scan for + * line We get the dependency list from here + * + * Global variables used: + */ +static Boolean +dependency_exists(Name target, Property line) +{ + Dependency dp; + + if (line == NULL) { + return false; + } + for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) { + if (dp->name == target) { + return true; + } + } + return false; +} + +void +add_target_to_chain(Name target, Chain * query) +{ + if (target->is_member && (get_prop(target->prop, member_prop) != NULL)) { + target = get_prop(target->prop, member_prop)->body.member.member; + } + Chain *query_tail; + for (query_tail = query; *query_tail != NULL; query_tail = &(*query_tail)->next) { + if ((*query_tail)->name == target) { + return; + } + } + *query_tail = ALLOC(Chain); + (*query_tail)->name = target; + (*query_tail)->next = NULL; +} + diff --git a/usr/src/make_src/Make/bin/make/common/macro.cc b/usr/src/make_src/Make/bin/make/common/macro.cc new file mode 100644 index 0000000..0f5bf82 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/macro.cc @@ -0,0 +1,214 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)macro.cc 1.28 06/12/12 + */ + +#pragma ident "@(#)macro.cc 1.28 06/12/12" + +/* + * macro.cc + * + * Handle expansion of make macros + */ + +/* + * Included files + */ +#ifdef DISTRIBUTED +#include <avo/strings.h> /* AVO_STRDUP() */ +#include <dm/Avo_DoJobMsg.h> +#endif +#include <mk/defs.h> +#include <mksh/macro.h> /* getvar(), expand_value() */ +#include <mksh/misc.h> /* getmem() */ + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +/* + * File table of contents + */ + +void +setvar_append(register Name name, register Name value) +{ + register Property macro_apx = get_prop(name->prop, macro_append_prop); + register Property macro = get_prop(name->prop, macro_prop); + int length; + String_rec destination; + wchar_t buffer[STRING_BUFFER_LENGTH]; + register Chain chain; + Name val = NULL; + + if(macro_apx == NULL) { + macro_apx = append_prop(name, macro_append_prop); + if(macro != NULL) { + macro_apx->body.macro_appendix.value = macro->body.macro.value; + } + } + + val = macro_apx->body.macro_appendix.value_to_append; + + INIT_STRING_FROM_STACK(destination, buffer); + buffer[0] = 0; + if (val != NULL) { + APPEND_NAME(val, + &destination, + (int) val->hash.length); + if (value != NULL) { + MBTOWC(wcs_buffer, " "); + append_char(wcs_buffer[0], &destination); + } + } + if (value != NULL) { + APPEND_NAME(value, + &destination, + (int) value->hash.length); + } + value = GETNAME(destination.buffer.start, FIND_LENGTH); + if (destination.free_after_use) { + retmem(destination.buffer.start); + } + macro_apx->body.macro_appendix.value_to_append = value; + + SETVAR(name, empty_name, true); +} + +/* + * setvar_envvar() + * + * This function scans the list of environment variables that have + * dynamic values and sets them. + * + * Parameters: + * + * Global variables used: + * envvar A list of environment vars with $ in value + */ +void +#ifdef DISTRIBUTED +setvar_envvar(Avo_DoJobMsg *dmake_job_msg) +#else +setvar_envvar(void) +#endif +{ + wchar_t buffer[STRING_BUFFER_LENGTH]; + int length; +#ifdef DISTRIBUTED + Property macro; +#endif + register char *mbs, *tmp_mbs_buffer = NULL; + register char *env, *tmp_mbs_buffer2 = NULL; + Envvar p; + String_rec value; + + for (p = envvar; p != NULL; p = p->next) { + if (p->already_put +#ifdef DISTRIBUTED + && !dmake_job_msg +#endif + ) { + continue; + } + INIT_STRING_FROM_STACK(value, buffer); + expand_value(p->value, &value, false); + if ((length = wslen(value.buffer.start)) >= MAXPATHLEN) { + mbs = tmp_mbs_buffer = getmem((length + 1) * MB_LEN_MAX); + (void) wcstombs(mbs, + value.buffer.start, + (length + 1) * MB_LEN_MAX); + } else { + mbs = mbs_buffer; + WCSTOMBS(mbs, value.buffer.start); + } + length = 2 + strlen(p->name->string_mb) + strlen(mbs); + if (!p->already_put || length > (MAXPATHLEN * MB_LEN_MAX)) { + env = tmp_mbs_buffer2 = getmem(length); + } else { + env = mbs_buffer2; + } + (void) sprintf(env, + "%s=%s", + p->name->string_mb, + mbs); + if (!p->already_put) { + (void) putenv(env); + p->already_put = true; + if (p->env_string) { + retmem_mb(p->env_string); + } + p->env_string = env; + tmp_mbs_buffer2 = NULL; // We should not return this memory now + } +#ifdef DISTRIBUTED + if (dmake_job_msg) { + dmake_job_msg->appendVar(env); + } +#endif + if (tmp_mbs_buffer2) { + retmem_mb(tmp_mbs_buffer2); + tmp_mbs_buffer2 = NULL; + } + if (tmp_mbs_buffer) { + retmem_mb(tmp_mbs_buffer); + tmp_mbs_buffer = NULL; + } + } +#ifdef DISTRIBUTED + /* Append SUNPRO_DEPENDENCIES to the dmake_job_msg. */ + if (keep_state && dmake_job_msg) { + macro = get_prop(sunpro_dependencies->prop, macro_prop); + length = 2 + + strlen(sunpro_dependencies->string_mb) + + strlen(macro->body.macro.value->string_mb); + if (length > (MAXPATHLEN * MB_LEN_MAX)) { + env = tmp_mbs_buffer2 = getmem(length); + } else { + env = mbs_buffer2; + } + (void) sprintf(env, + "%s=%s", + sunpro_dependencies->string_mb, + macro->body.macro.value->string_mb); + dmake_job_msg->appendVar(env); + if (tmp_mbs_buffer2) { + retmem_mb(tmp_mbs_buffer2); + tmp_mbs_buffer2 = NULL; + } + } +#endif +} + + diff --git a/usr/src/make_src/Make/bin/make/common/main.cc b/usr/src/make_src/Make/bin/make/common/main.cc new file mode 100644 index 0000000..e594d59 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/main.cc @@ -0,0 +1,3787 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)main.cc 1.158 06/12/12 + */ + +#pragma ident "@(#)main.cc 1.158 06/12/12" + +/* + * main.cc + * + * make program main routine plus some helper routines + */ + +/* + * Included files + */ +#if defined(TEAMWARE_MAKE_CMN) +# include <avo/intl.h> +# include <avo/libcli.h> /* libcli_init() */ +# include <avo/cli_license.h> /* avo_cli_get_license() */ +# include <avo/find_dir.h> /* avo_find_run_dir() */ +# include <avo/version_string.h> +# include <avo/util.h> /* avo_init() */ +#ifdef USE_DMS_CCR +# include <avo/usage_tracking.h> +#else +# include <avo/cleanup.h> +#endif +#endif + +#if defined(TEAMWARE_MAKE_CMN) +/* This is for dmake only (not for Solaris make). + * Include code to check updates (dmake patches) + */ +#ifdef _CHECK_UPDATE_H +#include <libAU.h> +#endif +#endif + +#include <bsd/bsd.h> /* bsd_signal() */ + +#ifdef DISTRIBUTED +# include <dm/Avo_AcknowledgeMsg.h> +# include <rw/xdrstrea.h> +# include <dmrc/dmrc.h> /* dmakerc file processing */ +#endif + +#include <locale.h> /* setlocale() */ +#include <mk/copyright.h> +#include <mk/defs.h> +#include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */ +#include <mksh/macro.h> /* getvar() */ +#include <mksh/misc.h> /* getmem(), setup_char_semantics() */ + +#if defined(TEAMWARE_MAKE_CMN) +#ifdef USE_DMS_CCR +# include <pubdmsi18n/pubdmsi18n.h> /* libpubdmsi18n_init() */ +#endif +#endif + +#include <pwd.h> /* getpwnam() */ +#include <setjmp.h> +#include <signal.h> +#include <stdlib.h> +#include <sys/errno.h> /* ENOENT */ +#include <sys/stat.h> /* fstat() */ +#include <fcntl.h> /* open() */ + +#ifdef SUN5_0 +# include <sys/systeminfo.h> /* sysinfo() */ +#endif + +#include <sys/types.h> /* stat() */ +#include <sys/wait.h> /* wait() */ +#include <unistd.h> /* execv(), unlink(), access() */ +#include <vroot/report.h> /* report_dependency(), get_report_file() */ + +// From read2.cc +extern Name normalize_name(register wchar_t *name_string, register int length); + +// From parallel.cc +#if defined(TEAMWARE_MAKE_CMN) +#define MAXJOBS_ADJUST_RFE4694000 + +#ifdef MAXJOBS_ADJUST_RFE4694000 +extern void job_adjust_fini(); +#endif /* MAXJOBS_ADJUST_RFE4694000 */ +#endif /* TEAMWARE_MAKE_CMN */ + +#if defined(linux) +#include <ctype.h> +#endif + +/* + * Defined macros + */ +#define LD_SUPPORT_ENV_VAR NOCATGETS("SGS_SUPPORT") +#define LD_SUPPORT_MAKE_LIB NOCATGETS("libmakestate.so.1") + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +static char *argv_zero_string; +static Boolean build_failed_ever_seen; +static Boolean continue_after_error_ever_seen; /* `-k' */ +static Boolean dmake_group_specified; /* `-g' */ +static Boolean dmake_max_jobs_specified; /* `-j' */ +static Boolean dmake_mode_specified; /* `-m' */ +static Boolean dmake_add_mode_specified; /* `-x' */ +static Boolean dmake_output_mode_specified; /* `-x DMAKE_OUTPUT_MODE=' */ +static Boolean dmake_compat_mode_specified; /* `-x SUN_MAKE_COMPAT_MODE=' */ +static Boolean dmake_odir_specified; /* `-o' */ +static Boolean dmake_rcfile_specified; /* `-c' */ +static Boolean env_wins; /* `-e' */ +static Boolean ignore_default_mk; /* `-r' */ +static Boolean list_all_targets; /* `-T' */ +static int mf_argc; +static char **mf_argv; +static Dependency_rec not_auto_depen_struct; +static Dependency not_auto_depen = ¬_auto_depen_struct; +static Boolean pmake_cap_r_specified; /* `-R' */ +static Boolean pmake_machinesfile_specified; /* `-M' */ +static Boolean stop_after_error_ever_seen; /* `-S' */ +static Boolean trace_status; /* `-p' */ + +#ifdef DMAKE_STATISTICS +static Boolean getname_stat = false; +#endif + +#if defined(TEAMWARE_MAKE_CMN) + static time_t start_time; + static int g_argc; + static char **g_argv; +#ifdef USE_DMS_CCR + static Avo_usage_tracking *usageTracking = NULL; +#else + static Avo_cleanup *cleanup = NULL; +#endif +#endif + +/* + * File table of contents + */ +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + extern "C" void cleanup_after_exit(void); +#else + extern void cleanup_after_exit(int, ...); +#endif + +#ifdef TEAMWARE_MAKE_CMN +extern "C" { + extern void dmake_exit_callback(void); + extern void dmake_message_callback(char *); +} +#endif + +extern Name normalize_name(register wchar_t *name_string, register int length); + +extern int main(int, char * []); + +static void append_makeflags_string(Name, String); +static void doalarm(int); +static void enter_argv_values(int , char **, ASCII_Dyn_Array *); +static void make_targets(int, char **, Boolean); +static int parse_command_option(char); +static void read_command_options(int, char **); +static void read_environment(Boolean); +static void read_files_and_state(int, char **); +static Boolean read_makefile(Name, Boolean, Boolean, Boolean); +static void report_recursion(Name); +static void set_sgs_support(void); +static void setup_for_projectdir(void); +static void setup_makeflags_argv(void); +static void report_dir_enter_leave(Boolean entering); + +extern void expand_value(Name, register String , Boolean); + +#ifdef DISTRIBUTED + extern int dmake_ofd; + extern FILE* dmake_ofp; + extern int rxmPid; + extern XDR xdrs_out; +#endif +#ifdef TEAMWARE_MAKE_CMN + extern char verstring[]; +#endif + +jmp_buf jmpbuffer; +#if !defined(linux) +nl_catd catd; +#endif + +/* + * main(argc, argv) + * + * Parameters: + * argc You know what this is + * argv You know what this is + * + * Static variables used: + * list_all_targets make -T seen + * trace_status make -p seen + * + * Global variables used: + * debug_level Should we trace make actions? + * keep_state Set if .KEEP_STATE seen + * makeflags The Name "MAKEFLAGS", used to get macro + * remote_command_name Name of remote invocation cmd ("on") + * running_list List of parallel running processes + * stdout_stderr_same true if stdout and stderr are the same + * auto_dependencies The Name "SUNPRO_DEPENDENCIES" + * temp_file_directory Set to the dir where we create tmp file + * trace_reader Set to reflect tracing status + * working_on_targets Set when building user targets + */ +int +main(int argc, char *argv[]) +{ + /* + * cp is a -> to the value of the MAKEFLAGS env var, + * which has to be regular chars. + */ + register char *cp; + char make_state_dir[MAXPATHLEN]; + Boolean parallel_flag = false; + char *prognameptr; + char *slash_ptr; + mode_t um; + int i; +#ifdef TEAMWARE_MAKE_CMN + struct itimerval value; + char def_dmakerc_path[MAXPATHLEN]; + Name dmake_name, dmake_name2; + Name dmake_value, dmake_value2; + Property prop, prop2; + struct stat statbuf; + int statval; +#endif + +#ifndef PARALLEL + struct stat out_stat, err_stat; +#endif + hostid = gethostid(); +#ifdef TEAMWARE_MAKE_CMN + avo_get_user(NULL, NULL); // Initialize user name +#endif + bsd_signals(); + + (void) setlocale(LC_ALL, ""); + +#if defined (HP_UX) || defined(linux) + /* HP-UX users typically will not have NLSPATH set, and this binary + * requires that it be set. On HP-UX 9.0x, /usr/lib/nls/%L/%N.cat is + * the path to set it to. + */ + + if (getenv(NOCATGETS("NLSPATH")) == NULL) { + putenv(NOCATGETS("NLSPATH=/usr/lib/nls/%L/%N.cat")); + } +#endif + +#ifdef DMAKE_STATISTICS + if (getenv(NOCATGETS("DMAKE_STATISTICS"))) { + getname_stat = true; + } +#endif + + + /* + * avo_init() sets the umask to 0. Save it here and restore + * it after the avo_init() call. + */ +#if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) + um = umask(0); + avo_init(argv[0]); + umask(um); + +#ifdef USE_DMS_CCR + usageTracking = new Avo_usage_tracking(NOCATGETS("dmake"), argc, argv); +#else + cleanup = new Avo_cleanup(NOCATGETS("dmake"), argc, argv); +#endif +#endif + +#if defined(TEAMWARE_MAKE_CMN) + catd = catopen(AVO_DOMAIN_DMAKE, NL_CAT_LOCALE); + libcli_init(); + +#ifdef _CHECK_UPDATE_H + /* This is for dmake only (not for Solaris make). + * Check (in background) if there is an update (dmake patch) + * and inform user + */ + { + Avo_err *err; + char *dir; + err = avo_find_run_dir(&dir); + if (AVO_OK == err) { + AU_check_update_service(NOCATGETS("Dmake"), dir); + } + } +#endif /* _CHECK_UPDATE_H */ +#endif + +// ---> fprintf(stderr, catgets(catd, 15, 666, "--- SUN make ---\n")); + + +#if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) +/* + * I put libmksdmsi18n_init() under #ifdef because it requires avo_i18n_init() + * from avo_util library. + */ + libmksdmsi18n_init(); +#ifdef USE_DMS_CCR + libpubdmsi18n_init(); +#endif +#endif + + +#ifndef TEAMWARE_MAKE_CMN + textdomain(NOCATGETS("SUNW_SPRO_MAKE")); +#endif /* TEAMWARE_MAKE_CMN */ + +#ifdef TEAMWARE_MAKE_CMN + g_argc = argc; + g_argv = (char **) malloc((g_argc + 1) * sizeof(char *)); + for (i = 0; i < argc; i++) { + g_argv[i] = argv[i]; + } + g_argv[i] = NULL; +#endif /* TEAMWARE_MAKE_CMN */ + + /* + * Set argv_zero_string to some form of argv[0] for + * recursive MAKE builds. + */ + + if (*argv[0] == (int) slash_char) { + /* argv[0] starts with a slash */ + argv_zero_string = strdup(argv[0]); + } else if (strchr(argv[0], (int) slash_char) == NULL) { + /* argv[0] contains no slashes */ + argv_zero_string = strdup(argv[0]); + } else { + /* + * argv[0] contains at least one slash, + * but doesn't start with a slash + */ + char *tmp_current_path; + char *tmp_string; + + tmp_current_path = get_current_path(); + tmp_string = getmem(strlen(tmp_current_path) + 1 + + strlen(argv[0]) + 1); + (void) sprintf(tmp_string, + "%s/%s", + tmp_current_path, + argv[0]); + argv_zero_string = strdup(tmp_string); + retmem_mb(tmp_string); + } + + /* + * The following flags are reset if we don't have the + * (.nse_depinfo or .make.state) files locked and only set + * AFTER the file has been locked. This ensures that if the user + * interrupts the program while file_lock() is waiting to lock + * the file, the interrupt handler doesn't remove a lock + * that doesn't belong to us. + */ + make_state_lockfile = NULL; + make_state_locked = false; + +#ifdef NSE + nse_depinfo_lockfile[0] = '\0'; + nse_depinfo_locked = false; +#endif + + /* + * look for last slash char in the path to look at the binary + * name. This is to resolve the hard link and invoke make + * in svr4 mode. + */ + + /* Sun OS make standart */ + svr4 = false; + posix = false; + if(!strcmp(argv_zero_string, NOCATGETS("/usr/xpg4/bin/make"))) { + svr4 = false; + posix = true; + } else { + prognameptr = strrchr(argv[0], '/'); + if(prognameptr) { + prognameptr++; + } else { + prognameptr = argv[0]; + } + if(!strcmp(prognameptr, NOCATGETS("svr4.make"))) { + svr4 = true; + posix = false; + } + } +#if !defined(HP_UX) && !defined(linux) + if (getenv(USE_SVR4_MAKE) || getenv(NOCATGETS("USE_SVID"))){ + svr4 = true; + posix = false; + } +#endif + + /* + * Find the dmake_compat_mode: posix, sun, svr4, or gnu_style, . + */ + char * dmake_compat_mode_var = getenv(NOCATGETS("SUN_MAKE_COMPAT_MODE")); + if (dmake_compat_mode_var != NULL) { + if (0 == strcasecmp(dmake_compat_mode_var, NOCATGETS("GNU"))) { + gnu_style = true; + } + //svr4 = false; + //posix = false; + } + + /* + * Temporary directory set up. + */ + char * tmpdir_var = getenv(NOCATGETS("TMPDIR")); + if (tmpdir_var != NULL && *tmpdir_var == '/' && strlen(tmpdir_var) < MAXPATHLEN) { + strcpy(mbs_buffer, tmpdir_var); + for (tmpdir_var = mbs_buffer+strlen(mbs_buffer); + *(--tmpdir_var) == '/' && tmpdir_var > mbs_buffer; + *tmpdir_var = '\0'); + if (strlen(mbs_buffer) + 32 < MAXPATHLEN) { /* 32 = strlen("/dmake.stdout.%d.%d.XXXXXX") */ + sprintf(mbs_buffer2, NOCATGETS("%s/dmake.tst.%d.XXXXXX"), + mbs_buffer, getpid()); + int fd = mkstemp(mbs_buffer2); + if (fd >= 0) { + close(fd); + unlink(mbs_buffer2); + tmpdir = strdup(mbs_buffer); + } + } + } + +#ifndef PARALLEL + /* find out if stdout and stderr point to the same place */ + if (fstat(1, &out_stat) < 0) { + fatal(catgets(catd, 1, 165, "fstat of standard out failed: %s"), errmsg(errno)); + } + if (fstat(2, &err_stat) < 0) { + fatal(catgets(catd, 1, 166, "fstat of standard error failed: %s"), errmsg(errno)); + } + if ((out_stat.st_dev == err_stat.st_dev) && + (out_stat.st_ino == err_stat.st_ino)) { + stdout_stderr_same = true; + } else { + stdout_stderr_same = false; + } +#else + stdout_stderr_same = false; +#endif + /* Make the vroot package scan the path using shell semantics */ + set_path_style(0); + + setup_char_semantics(); + + setup_for_projectdir(); + + /* + * If running with .KEEP_STATE, curdir will be set with + * the connected directory. + */ +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + (void) atexit(cleanup_after_exit); +#else + (void) on_exit(cleanup_after_exit, (char *) NULL); +#endif + + load_cached_names(); + +/* + * Set command line flags + */ + setup_makeflags_argv(); + read_command_options(mf_argc, mf_argv); + read_command_options(argc, argv); + if (debug_level > 0) { + cp = getenv(makeflags->string_mb); + (void) printf(catgets(catd, 1, 167, "MAKEFLAGS value: %s\n"), cp == NULL ? "" : cp); + } + + setup_interrupt(handle_interrupt); + + read_files_and_state(argc, argv); + +#ifdef TEAMWARE_MAKE_CMN + /* + * Find the dmake_output_mode: TXT1, TXT2 or HTML1. + */ + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); + dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); + prop2 = get_prop(dmake_name2->prop, macro_prop); + if (prop2 == NULL) { + /* DMAKE_OUTPUT_MODE not defined, default to TXT1 mode */ + output_mode = txt1_mode; + } else { + dmake_value2 = prop2->body.macro.value; + if ((dmake_value2 == NULL) || + (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT1")))) { + output_mode = txt1_mode; + } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("TXT2"))) { + output_mode = txt2_mode; + } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("HTML1"))) { + output_mode = html1_mode; + } else { + warning(catgets(catd, 1, 352, "Unsupported value `%s' for DMAKE_OUTPUT_MODE after -x flag (ignored)"), + dmake_value2->string_mb); + } + } + /* + * Find the dmake_mode: distributed, parallel, or serial. + */ + if ((!pmake_cap_r_specified) && + (!pmake_machinesfile_specified)) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); + dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); + prop2 = get_prop(dmake_name2->prop, macro_prop); + if (prop2 == NULL) { + /* DMAKE_MODE not defined, default to distributed mode */ + dmake_mode_type = distributed_mode; + no_parallel = false; + } else { + dmake_value2 = prop2->body.macro.value; + if ((dmake_value2 == NULL) || + (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("distributed")))) { + dmake_mode_type = distributed_mode; + no_parallel = false; + } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("parallel"))) { + dmake_mode_type = parallel_mode; + no_parallel = false; +#ifdef SGE_SUPPORT + grid = false; + } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("grid"))) { + dmake_mode_type = parallel_mode; + no_parallel = false; + grid = true; +#endif + } else if (IS_EQUAL(dmake_value2->string_mb, NOCATGETS("serial"))) { + dmake_mode_type = serial_mode; + no_parallel = true; + } else { + fatal(catgets(catd, 1, 307, "Unknown dmake mode argument `%s' after -m flag"), dmake_value2->string_mb); + } + } + + if ((!list_all_targets) && + (report_dependencies_level == 0)) { + /* + * Check to see if either DMAKE_RCFILE or DMAKE_MODE is defined. + * They could be defined in the env, in the makefile, or on the + * command line. + * If neither is defined, and $(HOME)/.dmakerc does not exists, + * then print a message, and default to parallel mode. + */ +#ifdef DISTRIBUTED + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); + dmake_name2 = GETNAME(wcs_buffer, FIND_LENGTH); + if ((((prop = get_prop(dmake_name->prop, macro_prop)) == NULL) || + ((dmake_value = prop->body.macro.value) == NULL)) && + (((prop2 = get_prop(dmake_name2->prop, macro_prop)) == NULL) || + ((dmake_value2 = prop2->body.macro.value) == NULL))) { + Boolean empty_dmakerc = true; + char *homedir = getenv(NOCATGETS("HOME")); + if ((homedir != NULL) && (strlen(homedir) < (sizeof(def_dmakerc_path) - 16))) { + sprintf(def_dmakerc_path, NOCATGETS("%s/.dmakerc"), homedir); + if ((((statval = stat(def_dmakerc_path, &statbuf)) != 0) && (errno == ENOENT)) || + ((statval == 0) && (statbuf.st_size == 0))) { + } else { + Avo_dmakerc *rcfile = new Avo_dmakerc(); + Avo_err *err = rcfile->read(def_dmakerc_path, NULL, TRUE); + if (err) { + fatal(err->str); + } + empty_dmakerc = rcfile->was_empty(); + delete rcfile; + } + } + if (empty_dmakerc) { + if (getenv(NOCATGETS("DMAKE_DEF_PRINTED")) == NULL) { + putenv(NOCATGETS("DMAKE_DEF_PRINTED=TRUE")); + (void) fprintf(stdout, catgets(catd, 1, 302, "dmake: defaulting to parallel mode.\n")); + (void) fprintf(stdout, catgets(catd, 1, 303, "See the man page dmake(1) for more information on setting up the .dmakerc file.\n")); + } + dmake_mode_type = parallel_mode; + no_parallel = false; + } + } +#else + if(dmake_mode_type == distributed_mode) { + (void) fprintf(stdout, NOCATGETS("dmake: Distributed mode not implemented.\n")); + (void) fprintf(stdout, NOCATGETS(" Defaulting to parallel mode.\n")); + dmake_mode_type = parallel_mode; + no_parallel = false; + } +#endif /* DISTRIBUTED */ + } + } +#endif + +#ifdef TEAMWARE_MAKE_CMN + parallel_flag = true; + /* XXX - This is a major hack for DMake/Licensing. */ + if (getenv(NOCATGETS("DMAKE_CHILD")) == NULL) { + if (!avo_cli_search_license(argv[0], dmake_exit_callback, TRUE, dmake_message_callback)) { + /* + * If the user can not get a TeamWare license, + * default to serial mode. + */ + dmake_mode_type = serial_mode; + no_parallel = true; + } else { + putenv(NOCATGETS("DMAKE_CHILD=TRUE")); + } + start_time = time(NULL); + /* + * XXX - Hack to disable SIGALRM's from licensing library's + * setitimer(). + */ + value.it_interval.tv_sec = 0; + value.it_interval.tv_usec = 0; + value.it_value.tv_sec = 0; + value.it_value.tv_usec = 0; + (void) setitimer(ITIMER_REAL, &value, NULL); + } + +// +// If dmake is running with -t option, set dmake_mode_type to serial. +// This is done because doname() calls touch_command() that runs serially. +// If we do not do that, maketool will have problems. +// + if(touch) { + dmake_mode_type = serial_mode; + no_parallel = true; + } +#else + parallel_flag = false; +#endif + +#if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR) + /* + * Check whether stdout and stderr are physically same. + * This is in order to decide whether we need to redirect + * stderr separately from stdout. + * This check is performed only if __DMAKE_SEPARATE_STDERR + * is not set. This variable may be used in order to preserve + * the 'old' behaviour. + */ + out_err_same = true; + char * dmake_sep_var = getenv(NOCATGETS("__DMAKE_SEPARATE_STDERR")); + if (dmake_sep_var == NULL || (0 != strcasecmp(dmake_sep_var, NOCATGETS("NO")))) { + struct stat stdout_stat; + struct stat stderr_stat; + if( (fstat(1, &stdout_stat) == 0) + && (fstat(2, &stderr_stat) == 0) ) + { + if( (stdout_stat.st_dev != stderr_stat.st_dev) + || (stdout_stat.st_ino != stderr_stat.st_ino) ) + { + out_err_same = false; + } + } + } +#endif + +#ifdef DISTRIBUTED + /* + * At this point, DMake should startup an rxm with any and all + * DMake command line options. Rxm will, among other things, + * read the rc file. + */ + if ((!list_all_targets) && + (report_dependencies_level == 0) && + (dmake_mode_type == distributed_mode)) { + startup_rxm(); + } +#endif + +/* + * Enable interrupt handler for alarms + */ + (void) bsd_signal(SIGALRM, (SIG_PF)doalarm); + +/* + * Check if make should report + */ + if (getenv(sunpro_dependencies->string_mb) != NULL) { + FILE *report_file; + + report_dependency(""); + report_file = get_report_file(); + if ((report_file != NULL) && (report_file != (FILE*)-1)) { + (void) fprintf(report_file, "\n"); + } + } + +/* + * Make sure SUNPRO_DEPENDENCIES is exported (or not) properly + * and NSE_DEP. + */ + if (keep_state) { + maybe_append_prop(sunpro_dependencies, macro_prop)-> + body.macro.exported = true; +#ifdef NSE + (void) setenv(NOCATGETS("NSE_DEP"), get_current_path()); +#endif + } else { + maybe_append_prop(sunpro_dependencies, macro_prop)-> + body.macro.exported = false; + } + + working_on_targets = true; + if (trace_status) { + dump_make_state(); +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + fclose(stdout); + fclose(stderr); + exit_status = 0; +#endif + exit(0); + } + if (list_all_targets) { + dump_target_list(); +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + fclose(stdout); + fclose(stderr); + exit_status = 0; +#endif + exit(0); + } + trace_reader = false; + + /* + * Set temp_file_directory to the directory the .make.state + * file is written to. + */ + if ((slash_ptr = strrchr(make_state->string_mb, (int) slash_char)) == NULL) { + temp_file_directory = strdup(get_current_path()); + } else { + *slash_ptr = (int) nul_char; + (void) strcpy(make_state_dir, make_state->string_mb); + *slash_ptr = (int) slash_char; + /* when there is only one slash and it's the first + ** character, make_state_dir should point to '/'. + */ + if(make_state_dir[0] == '\0') { + make_state_dir[0] = '/'; + make_state_dir[1] = '\0'; + } + if (make_state_dir[0] == (int) slash_char) { + temp_file_directory = strdup(make_state_dir); + } else { + char tmp_current_path2[MAXPATHLEN]; + + (void) sprintf(tmp_current_path2, + "%s/%s", + get_current_path(), + make_state_dir); + temp_file_directory = strdup(tmp_current_path2); + } + } + +#ifdef DISTRIBUTED + building_serial = false; +#endif + + report_dir_enter_leave(true); + + make_targets(argc, argv, parallel_flag); + + report_dir_enter_leave(false); + +#ifdef NSE + exit(nse_exit_status()); +#else + if (build_failed_ever_seen) { +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + if (posix) { + exit_status = 1; + } +#endif + exit(1); + } +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + exit_status = 0; +#endif + exit(0); +#endif + /* NOTREACHED */ +} + +/* + * cleanup_after_exit() + * + * Called from exit(), performs cleanup actions. + * + * Parameters: + * status The argument exit() was called with + * arg Address of an argument vector to + * cleanup_after_exit() + * + * Global variables used: + * command_changed Set if we think .make.state should be rewritten + * current_line Is set we set commands_changed + * do_not_exec_rule + * True if -n flag on + * done The Name ".DONE", rule we run + * keep_state Set if .KEEP_STATE seen + * parallel True if building in parallel + * quest If -q is on we do not run .DONE + * report_dependencies + * True if -P flag on + * running_list List of parallel running processes + * temp_file_name The temp file is removed, if any + * catd the message catalog file + * usage_tracking Should have been constructed in main() + * should destroyed just before exiting + */ +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) +extern "C" void +cleanup_after_exit(void) +#else +void cleanup_after_exit(int status, ...) +#endif +{ + Running rp; +#ifdef NSE + char push_cmd[NSE_TFS_PUSH_LEN + 3 + + (MAXPATHLEN * MB_LEN_MAX) + 12]; + char *active; +#endif + +extern long getname_bytes_count; +extern long getname_names_count; +extern long getname_struct_count; +extern long freename_bytes_count; +extern long freename_names_count; +extern long freename_struct_count; +extern long other_alloc; + +extern long env_alloc_num; +extern long env_alloc_bytes; + + +#ifdef DMAKE_STATISTICS +if(getname_stat) { + printf(NOCATGETS(">>> Getname statistics:\n")); + printf(NOCATGETS(" Allocated:\n")); + printf(NOCATGETS(" Names: %ld\n"), getname_names_count); + printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), getname_bytes_count/1000, getname_bytes_count); + printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), getname_struct_count/1000, getname_struct_count); + printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), getname_struct_count/1000 + getname_bytes_count/1000, getname_struct_count + getname_bytes_count); + + printf(NOCATGETS("\n Unallocated: %ld\n"), freename_names_count); + printf(NOCATGETS(" Names: %ld\n"), freename_names_count); + printf(NOCATGETS(" Strings: %ld Kb (%ld bytes)\n"), freename_bytes_count/1000, freename_bytes_count); + printf(NOCATGETS(" Structs: %ld Kb (%ld bytes)\n"), freename_struct_count/1000, freename_struct_count); + printf(NOCATGETS(" Total bytes: %ld Kb (%ld bytes)\n"), freename_struct_count/1000 + freename_bytes_count/1000, freename_struct_count + freename_bytes_count); + + printf(NOCATGETS("\n Total used: %ld Kb (%ld bytes)\n"), (getname_struct_count/1000 + getname_bytes_count/1000) - (freename_struct_count/1000 + freename_bytes_count/1000), (getname_struct_count + getname_bytes_count) - (freename_struct_count + freename_bytes_count)); + + printf(NOCATGETS("\n>>> Other:\n")); + printf( + NOCATGETS(" Env (%ld): %ld Kb (%ld bytes)\n"), + env_alloc_num, + env_alloc_bytes/1000, + env_alloc_bytes + ); + +} +#endif + +/* +#ifdef DISTRIBUTED + if (get_parent() == TRUE) { +#endif + */ + + parallel = false; +#ifdef SUN5_0 + /* If we used the SVR4_MAKE, don't build .DONE or .FAILED */ + if (!getenv(USE_SVR4_MAKE)){ +#endif + /* Build the target .DONE or .FAILED if we caught an error */ + if (!quest && !list_all_targets) { + Name failed_name; + + MBSTOWCS(wcs_buffer, NOCATGETS(".FAILED")); + failed_name = GETNAME(wcs_buffer, FIND_LENGTH); +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + if ((exit_status != 0) && (failed_name->prop != NULL)) { +#else + if ((status != 0) && (failed_name->prop != NULL)) { +#endif +#ifdef TEAMWARE_MAKE_CMN + /* + * [tolik] switch DMake to serial mode + */ + dmake_mode_type = serial_mode; + no_parallel = true; +#endif + (void) doname(failed_name, false, true); + } else { + if (!trace_status) { +#ifdef TEAMWARE_MAKE_CMN + /* + * Switch DMake to serial mode + */ + dmake_mode_type = serial_mode; + no_parallel = true; +#endif + (void) doname(done, false, true); + } + } + } +#ifdef SUN5_0 + } +#endif + /* + * Remove the temp file utilities report dependencies thru if it + * is still around + */ + if (temp_file_name != NULL) { + (void) unlink(temp_file_name->string_mb); + } + /* + * Do not save the current command in .make.state if make + * was interrupted. + */ + if (current_line != NULL) { + command_changed = true; + current_line->body.line.command_used = NULL; + } + /* + * For each parallel build process running, remove the temp files + * and zap the command line so it won't be put in .make.state + */ + for (rp = running_list; rp != NULL; rp = rp->next) { + if (rp->temp_file != NULL) { + (void) unlink(rp->temp_file->string_mb); + } + if (rp->stdout_file != NULL) { + (void) unlink(rp->stdout_file); + retmem_mb(rp->stdout_file); + rp->stdout_file = NULL; + } + if (rp->stderr_file != NULL) { + (void) unlink(rp->stderr_file); + retmem_mb(rp->stderr_file); + rp->stderr_file = NULL; + } + command_changed = true; +/* + line = get_prop(rp->target->prop, line_prop); + if (line != NULL) { + line->body.line.command_used = NULL; + } + */ + } + /* Remove the statefile lock file if the file has been locked */ + if ((make_state_lockfile != NULL) && (make_state_locked)) { + (void) unlink(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } + /* Write .make.state */ + write_state_file(1, (Boolean) 1); + +#ifdef TEAMWARE_MAKE_CMN + // Deleting the usage tracking object sends the usage mail +#ifdef USE_DMS_CCR + //usageTracking->setExitStatus(exit_status, NULL); + //delete usageTracking; +#else + cleanup->set_exit_status(exit_status); + delete cleanup; +#endif +#endif + +#ifdef NSE + /* If running inside an activated environment, push the */ + /* .nse_depinfo file (if written) */ + active = getenv(NSE_VARIANT_ENV); + if (keep_state && + (active != NULL) && + !IS_EQUAL(active, NSE_RT_SOURCE_NAME) && + !do_not_exec_rule && + (report_dependencies_level == 0)) { + (void) sprintf(push_cmd, + "%s %s/%s", + NSE_TFS_PUSH, + get_current_path(), + NSE_DEPINFO); + (void) system(push_cmd); + } +#endif + +/* +#ifdef DISTRIBUTED + } +#endif + */ + +#if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000) + job_adjust_fini(); +#endif + +#ifdef TEAMWARE_MAKE_CMN + catclose(catd); +#endif +#ifdef DISTRIBUTED + if (rxmPid > 0) { + // Tell rxm to exit by sending it an Avo_AcknowledgeMsg + Avo_AcknowledgeMsg acknowledgeMsg; + RWCollectable *msg = (RWCollectable *)&acknowledgeMsg; + + int xdrResult = xdr(&xdrs_out, msg); + + if (xdrResult) { + fflush(dmake_ofp); + } else { +/* + fatal(catgets(catd, 1, 266, "couldn't tell rxm to exit")); + */ + kill(rxmPid, SIGTERM); + } + + waitpid(rxmPid, NULL, 0); + rxmPid = 0; + } +#endif +} + +/* + * handle_interrupt() + * + * This is where C-C traps are caught. + * + * Parameters: + * + * Global variables used (except DMake 1.0): + * current_target Sometimes the current target is removed + * do_not_exec_rule But not if -n is on + * quest or -q + * running_list List of parallel running processes + * touch Current target is not removed if -t on + */ +void +handle_interrupt(int) +{ + Property member; + Running rp; + + (void) fflush(stdout); +#ifdef DISTRIBUTED + if (rxmPid > 0) { + // Tell rxm to exit by sending it an Avo_AcknowledgeMsg + Avo_AcknowledgeMsg acknowledgeMsg; + RWCollectable *msg = (RWCollectable *)&acknowledgeMsg; + + int xdrResult = xdr(&xdrs_out, msg); + + if (xdrResult) { + fflush(dmake_ofp); + } else { + kill(rxmPid, SIGTERM); + rxmPid = 0; + } + } +#endif + if (childPid > 0) { + kill(childPid, SIGTERM); + childPid = -1; + } + for (rp = running_list; rp != NULL; rp = rp->next) { + if (rp->state != build_running) { + continue; + } + if (rp->pid > 0) { + kill(rp->pid, SIGTERM); + rp->pid = -1; + } + } + if (getpid() == getpgrp()) { + bsd_signal(SIGTERM, SIG_IGN); + kill (-getpid(), SIGTERM); + } +#ifdef TEAMWARE_MAKE_CMN + /* Clean up all parallel/distributed children already finished */ + finish_children(false); +#endif + + /* Make sure the processes running under us terminate first */ + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + while (wait((int *) NULL) != -1); +#else + while (wait((union wait*) NULL) != -1); +#endif + /* Delete the current targets unless they are precious */ + if ((current_target != NULL) && + current_target->is_member && + ((member = get_prop(current_target->prop, member_prop)) != NULL)) { + current_target = member->body.member.library; + } + if (!do_not_exec_rule && + !touch && + !quest && + (current_target != NULL) && + !(current_target->stat.is_precious || all_precious)) { + +/* BID_1030811 */ +/* azv 16 Oct 95 */ + current_target->stat.time = file_no_time; + + if (exists(current_target) != file_doesnt_exist) { + (void) fprintf(stderr, + "\n*** %s ", + current_target->string_mb); + if (current_target->stat.is_dir) { + (void) fprintf(stderr, + catgets(catd, 1, 168, "not removed.\n"), + current_target->string_mb); + } else if (unlink(current_target->string_mb) == 0) { + (void) fprintf(stderr, + catgets(catd, 1, 169, "removed.\n"), + current_target->string_mb); + } else { + (void) fprintf(stderr, + catgets(catd, 1, 170, "could not be removed: %s.\n"), + current_target->string_mb, + errmsg(errno)); + } + } + } + for (rp = running_list; rp != NULL; rp = rp->next) { + if (rp->state != build_running) { + continue; + } + if (rp->target->is_member && + ((member = get_prop(rp->target->prop, member_prop)) != + NULL)) { + rp->target = member->body.member.library; + } + if (!do_not_exec_rule && + !touch && + !quest && + !(rp->target->stat.is_precious || all_precious)) { + + rp->target->stat.time = file_no_time; + if (exists(rp->target) != file_doesnt_exist) { + (void) fprintf(stderr, + "\n*** %s ", + rp->target->string_mb); + if (rp->target->stat.is_dir) { + (void) fprintf(stderr, + catgets(catd, 1, 171, "not removed.\n"), + rp->target->string_mb); + } else if (unlink(rp->target->string_mb) == 0) { + (void) fprintf(stderr, + catgets(catd, 1, 172, "removed.\n"), + rp->target->string_mb); + } else { + (void) fprintf(stderr, + catgets(catd, 1, 173, "could not be removed: %s.\n"), + rp->target->string_mb, + errmsg(errno)); + } + } + } + } + +#ifdef SGE_SUPPORT + /* Remove SGE script file */ + if (grid) { + unlink(script_file); + } +#endif + + /* Have we locked .make.state or .nse_depinfo? */ + if ((make_state_lockfile != NULL) && (make_state_locked)) { + unlink(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } +#ifdef NSE + if ((nse_depinfo_lockfile[0] != '\0') && (nse_depinfo_locked)) { + unlink(nse_depinfo_lockfile); + nse_depinfo_lockfile[0] = '\0'; + nse_depinfo_locked = false; + } +#endif + /* + * Re-read .make.state file (it might be changed by recursive make) + */ + check_state(NULL); + + report_dir_enter_leave(false); + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + exit_status = 2; +#endif + exit(2); +} + +/* + * doalarm(sig, ...) + * + * Handle the alarm interrupt but do nothing. Side effect is to + * cause return from wait3. + * + * Parameters: + * sig + * + * Global variables used: + */ +/*ARGSUSED*/ +static void +doalarm(int) +{ + return; +} + + +/* + * read_command_options(argc, argv) + * + * Scan the cmd line options and process the ones that start with "-" + * + * Return value: + * -M argument, if any + * + * Parameters: + * argc You know what this is + * argv You know what this is + * + * Global variables used: + */ +static void +read_command_options(register int argc, register char **argv) +{ + register int ch; + int current_optind = 1; + int last_optind_with_double_hyphen = 0; + int last_optind; + int last_current_optind; + register int i; + register int j; + register int k; + register int makefile_next = 0; /* + * flag to note options: + * -c, f, g, j, m, o + */ + const char *tptr; + const char *CMD_OPTS; + + extern char *optarg; + extern int optind, opterr, optopt; + +#define SUNPRO_CMD_OPTS "-~Bbc:Ddef:g:ij:K:kM:m:NnO:o:PpqRrSsTtuVvwx:" + +#ifdef TEAMWARE_MAKE_CMN +# define SVR4_CMD_OPTS "-c:ef:g:ij:km:nO:o:pqrsTtVv" +#else +# define SVR4_CMD_OPTS "-ef:iknpqrstV" +#endif + + /* + * Added V in SVR4_CMD_OPTS also, which is going to be a hidden + * option, just to make sure that the getopt doesn't fail when some + * users leave their USE_SVR4_MAKE set and try to use the makefiles + * that are designed to issue commands like $(MAKE) -V. Anyway it + * sets the same flag but ensures that getopt doesn't fail. + */ + + opterr = 0; + optind = 1; + while (1) { + last_optind=optind; /* Save optind and current_optind values */ + last_current_optind=current_optind; /* in case we have to repeat this round. */ + if (svr4) { + CMD_OPTS=SVR4_CMD_OPTS; + ch = getopt(argc, argv, SVR4_CMD_OPTS); + } else { + CMD_OPTS=SUNPRO_CMD_OPTS; + ch = getopt(argc, argv, SUNPRO_CMD_OPTS); + } + if (ch == EOF) { + if(optind < argc) { + /* + * Fixing bug 4102537: + * Strange behaviour of command make using -- option. + * Not all argv have been processed + * Skip non-flag argv and continue processing. + */ + optind++; + current_optind++; + continue; + } else { + break; + } + + } + if (ch == '?') { + if (optopt == '-') { + /* Bug 5060758: getopt() changed behavior (s10_60), + * and now we have to deal with cases when options + * with double hyphen appear here, from -$(MAKEFLAGS) + */ + i = current_optind; + if (argv[i][0] == '-') { + if (argv[i][1] == '-') { + if (argv[i][2] != '\0') { + /* Check if this option is allowed */ + tptr = strchr(CMD_OPTS, argv[i][2]); + if (tptr) { + if (last_optind_with_double_hyphen != current_optind) { + /* This is first time we are trying to fix "--" + * problem with this option. If we come here second + * time, we will go to fatal error. + */ + last_optind_with_double_hyphen = current_optind; + + /* Eliminate first hyphen character */ + for (j=0; argv[i][j] != '\0'; j++) { + argv[i][j] = argv[i][j+1]; + } + + /* Repeat the processing of this argument */ + optind=last_optind; + current_optind=last_current_optind; + continue; + } + } + } + } + } + } + } + + if (ch == '?') { + if (svr4) { +#ifdef TEAMWARE_MAKE_CMN + fprintf(stderr, + catgets(catd, 1, 267, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n")); + fprintf(stderr, + catgets(catd, 1, 268, " [ -j dmake_max_jobs ][ -m dmake_mode ][ -o dmake_odir ]...\n")); + fprintf(stderr, + catgets(catd, 1, 269, " [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ][ -s ][ -t ][ -v ]\n")); +#else + fprintf(stderr, + catgets(catd, 1, 270, "Usage : make [ -f makefile ]... [ -e ][ -i ][ -k ][ -n ][ -p ][ -q ][ -r ]\n")); + fprintf(stderr, + catgets(catd, 1, 271, " [ -s ][ -t ]\n")); +#endif + tptr = strchr(SVR4_CMD_OPTS, optopt); + } else { +#ifdef TEAMWARE_MAKE_CMN + fprintf(stderr, + catgets(catd, 1, 272, "Usage : dmake [ -f makefile ][ -c dmake_rcfile ][ -g dmake_group ]\n")); + fprintf(stderr, + catgets(catd, 1, 273, " [ -j dmake_max_jobs ][ -K statefile ][ -m dmake_mode ][ -x MODE_NAME=VALUE ][ -o dmake_odir ]...\n")); + fprintf(stderr, + catgets(catd, 1, 274, " [ -d ][ -dd ][ -D ][ -DD ][ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -u ][ -w ]\n")); + fprintf(stderr, + catgets(catd, 1, 275, " [ -q ][ -r ][ -s ][ -S ][ -t ][ -v ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); +#else + fprintf(stderr, + catgets(catd, 1, 276, "Usage : make [ -f makefile ][ -K statefile ]... [ -d ][ -dd ][ -D ][ -DD ]\n")); + fprintf(stderr, + catgets(catd, 1, 277, " [ -e ][ -i ][ -k ][ -n ][ -p ][ -P ][ -q ][ -r ][ -s ][ -S ][ -t ]\n")); + fprintf(stderr, + catgets(catd, 1, 278, " [ -u ][ -w ][ -V ][ target... ][ macro=value... ][ \"macro +=value\"... ]\n")); +#endif + tptr = strchr(SUNPRO_CMD_OPTS, optopt); + } + if (!tptr) { + fatal(catgets(catd, 1, 279, "Unknown option `-%c'"), optopt); + } else { + fatal(catgets(catd, 1, 280, "Missing argument after `-%c'"), optopt); + } + } + +#if defined(linux) + if (ch == 1) { + if(optind < argc) { + //optind++; + //current_optind++; + makefile_next = 0; + current_optind = optind; + continue; + } else { + break; + } + } +#endif + + + makefile_next |= parse_command_option(ch); + /* + * If we're done processing all of the options of + * ONE argument string... + */ + if (current_optind < optind) { + i = current_optind; + k = 0; + /* If there's an argument for an option... */ + if ((optind - current_optind) > 1) { + k = i + 1; + } + switch (makefile_next) { + case 0: + argv[i] = NULL; + /* This shouldn't happen */ + if (k) { + argv[k] = NULL; + } + break; + case 1: /* -f seen */ + argv[i] = NOCATGETS("-f"); + break; + case 2: /* -c seen */ + argv[i] = NOCATGETS("-c"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 281, "Ignoring DistributedMake -c option")); +#endif + break; + case 4: /* -g seen */ + argv[i] = NOCATGETS("-g"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 282, "Ignoring DistributedMake -g option")); +#endif + break; + case 8: /* -j seen */ + argv[i] = NOCATGETS("-j"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 283, "Ignoring DistributedMake -j option")); +#endif + break; + case 16: /* -M seen */ + argv[i] = NOCATGETS("-M"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 284, "Ignoring ParallelMake -M option")); +#endif + break; + case 32: /* -m seen */ + argv[i] = NOCATGETS("-m"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 285, "Ignoring DistributedMake -m option")); +#endif + break; +#ifndef PARALLEL + case 128: /* -O seen */ + argv[i] = NOCATGETS("-O"); + break; +#endif + case 256: /* -K seen */ + argv[i] = NOCATGETS("-K"); + break; + case 512: /* -o seen */ + argv[i] = NOCATGETS("-o"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 311, "Ignoring DistributedMake -o option")); +#endif + break; + case 1024: /* -x seen */ + argv[i] = NOCATGETS("-x"); +#ifndef TEAMWARE_MAKE_CMN + warning(catgets(catd, 1, 353, "Ignoring DistributedMake -x option")); +#endif + break; + default: /* > 1 of -c, f, g, j, K, M, m, O, o, x seen */ + fatal(catgets(catd, 1, 286, "Illegal command line. More than one option requiring\nan argument given in the same argument group")); + } + + makefile_next = 0; + current_optind = optind; + } + } +} + +static void +quote_str(char *str, char *qstr) +{ + char *to; + char *from; + + to = qstr; + for (from = str; *from; from++) { + switch (*from) { + case ';': /* End of command */ + case '(': /* Start group */ + case ')': /* End group */ + case '{': /* Start group */ + case '}': /* End group */ + case '[': /* Reg expr - any of a set of chars */ + case ']': /* End of set of chars */ + case '|': /* Pipe or logical-or */ + case '^': /* Old-fashioned pipe */ + case '&': /* Background or logical-and */ + case '<': /* Redirect stdin */ + case '>': /* Redirect stdout */ + case '*': /* Reg expr - any sequence of chars */ + case '?': /* Reg expr - any single char */ + case '$': /* Variable substitution */ + case '\'': /* Singe quote - turn off all magic */ + case '"': /* Double quote - span whitespace */ + case '`': /* Backquote - run a command */ + case '#': /* Comment */ + case ' ': /* Space (for MACRO=value1 value2 */ + case '\\': /* Escape char - turn off magic of next char */ + *to++ = '\\'; + break; + + default: + break; + } + *to++ = *from; + } + *to = '\0'; +} + +static void +unquote_str(char *str, char *qstr) +{ + char *to; + char *from; + + to = qstr; + for (from = str; *from; from++) { + if (*from == '\\') { + from++; + } + *to++ = *from; + } + *to = '\0'; +} + +/* + * Convert the MAKEFLAGS string value into a vector of char *, similar + * to argv. + */ +static void +setup_makeflags_argv() +{ + char *cp; + char *cp1; + char *cp2; + char *cp3; + char *cp_orig; + Boolean add_hyphen; + int i; + char tmp_char; + + mf_argc = 1; + cp = getenv(makeflags->string_mb); + cp_orig = cp; + + if (cp) { + /* + * If new MAKEFLAGS format, no need to add hyphen. + * If old MAKEFLAGS format, add hyphen before flags. + */ + + if ((strchr(cp, (int) hyphen_char) != NULL) || + (strchr(cp, (int) equal_char) != NULL)) { + + /* New MAKEFLAGS format */ + + add_hyphen = false; +#ifdef ADDFIX5060758 + /* Check if MAKEFLAGS value begins with multiple + * hyphen characters, and remove all duplicates. + * Usually it happens when the next command is + * used: $(MAKE) -$(MAKEFLAGS) + * This is a workaround for BugID 5060758. + */ + while (*cp) { + if (*cp != (int) hyphen_char) { + break; + } + cp++; + if (*cp == (int) hyphen_char) { + /* There are two hyphens. Skip one */ + cp_orig = cp; + cp++; + } + if (!(*cp)) { + /* There are hyphens only. Skip all */ + cp_orig = cp; + break; + } + } +#endif + } else { + + /* Old MAKEFLAGS format */ + + add_hyphen = true; + } + } + + /* Find the number of arguments in MAKEFLAGS */ + while (cp && *cp) { + /* Skip white spaces */ + while (cp && *cp && isspace(*cp)) { + cp++; + } + if (cp && *cp) { + /* Increment arg count */ + mf_argc++; + /* Go to next white space */ + while (cp && *cp && !isspace(*cp)) { + if(*cp == (int) backslash_char) { + cp++; + } + cp++; + } + } + } + /* Allocate memory for the new MAKEFLAGS argv */ + mf_argv = (char **) malloc((mf_argc + 1) * sizeof(char *)); + mf_argv[0] = NOCATGETS("MAKEFLAGS"); + /* + * Convert the MAKEFLAGS string value into a vector of char *, + * similar to argv. + */ + cp = cp_orig; + for (i = 1; i < mf_argc; i++) { + /* Skip white spaces */ + while (cp && *cp && isspace(*cp)) { + cp++; + } + if (cp && *cp) { + cp_orig = cp; + /* Go to next white space */ + while (cp && *cp && !isspace(*cp)) { + if(*cp == (int) backslash_char) { + cp++; + } + cp++; + } + tmp_char = *cp; + *cp = (int) nul_char; + if (add_hyphen) { + mf_argv[i] = getmem(2 + strlen(cp_orig)); + mf_argv[i][0] = '\0'; + (void) strcat(mf_argv[i], "-"); + // (void) strcat(mf_argv[i], cp_orig); + unquote_str(cp_orig, mf_argv[i]+1); + } else { + mf_argv[i] = getmem(2 + strlen(cp_orig)); + //mf_argv[i] = strdup(cp_orig); + unquote_str(cp_orig, mf_argv[i]); + } + *cp = tmp_char; + } + } + mf_argv[i] = NULL; +} + +/* + * parse_command_option(ch) + * + * Parse make command line options. + * + * Return value: + * Indicates if any -f -c or -M were seen + * + * Parameters: + * ch The character to parse + * + * Static variables used: + * dmake_group_specified Set for make -g + * dmake_max_jobs_specified Set for make -j + * dmake_mode_specified Set for make -m + * dmake_add_mode_specified Set for make -x + * dmake_compat_mode_specified Set for make -x SUN_MAKE_COMPAT_MODE= + * dmake_output_mode_specified Set for make -x DMAKE_OUTPUT_MODE= + * dmake_odir_specified Set for make -o + * dmake_rcfile_specified Set for make -c + * env_wins Set for make -e + * ignore_default_mk Set for make -r + * trace_status Set for make -p + * + * Global variables used: + * .make.state path & name set for make -K + * continue_after_error Set for make -k + * debug_level Set for make -d + * do_not_exec_rule Set for make -n + * filter_stderr Set for make -X + * ignore_errors_all Set for make -i + * no_parallel Set for make -R + * quest Set for make -q + * read_trace_level Set for make -D + * report_dependencies Set for make -P + * send_mtool_msgs Set for make -K + * silent_all Set for make -s + * touch Set for make -t + */ +static int +parse_command_option(register char ch) +{ + static int invert_next = 0; + int invert_this = invert_next; + + invert_next = 0; + switch (ch) { + case '-': /* Ignore "--" */ + return 0; + case '~': /* Invert next option */ + invert_next = 1; + return 0; + case 'B': /* Obsolete */ + return 0; + case 'b': /* Obsolete */ + return 0; + case 'c': /* Read alternative dmakerc file */ + if (invert_this) { + dmake_rcfile_specified = false; + } else { + dmake_rcfile_specified = true; + } + return 2; + case 'D': /* Show lines read */ + if (invert_this) { + read_trace_level--; + } else { + read_trace_level++; + } + return 0; + case 'd': /* Debug flag */ + if (invert_this) { + debug_level--; + } else { +#if defined( HP_UX) || defined(linux) + if (debug_level < 2) /* Fixes a bug on HP-UX */ +#endif + debug_level++; + } + return 0; +#ifdef NSE + case 'E': + if (invert_this) { + nse = false; + } else { + nse = true; + } + nse_init_source_suffixes(); + return 0; +#endif + case 'e': /* Environment override flag */ + if (invert_this) { + env_wins = false; + } else { + env_wins = true; + } + return 0; + case 'f': /* Read alternative makefile(s) */ + return 1; + case 'g': /* Use alternative DMake group */ + if (invert_this) { + dmake_group_specified = false; + } else { + dmake_group_specified = true; + } + return 4; + case 'i': /* Ignore errors */ + if (invert_this) { + ignore_errors_all = false; + } else { + ignore_errors_all = true; + } + return 0; + case 'j': /* Use alternative DMake max jobs */ + if (invert_this) { + dmake_max_jobs_specified = false; + } else { + dmake_max_jobs_specified = true; + } + return 8; + case 'K': /* Read alternative .make.state */ + return 256; + case 'k': /* Keep making even after errors */ + if (invert_this) { + continue_after_error = false; + } else { + continue_after_error = true; + continue_after_error_ever_seen = true; + } + return 0; + case 'M': /* Read alternative make.machines file */ + if (invert_this) { + pmake_machinesfile_specified = false; + } else { + pmake_machinesfile_specified = true; + dmake_mode_type = parallel_mode; + no_parallel = false; + } + return 16; + case 'm': /* Use alternative DMake build mode */ + if (invert_this) { + dmake_mode_specified = false; + } else { + dmake_mode_specified = true; + } + return 32; + case 'x': /* Use alternative DMake mode */ + if (invert_this) { + dmake_add_mode_specified = false; + } else { + dmake_add_mode_specified = true; + } + return 1024; + case 'N': /* Reverse -n */ + if (invert_this) { + do_not_exec_rule = true; + } else { + do_not_exec_rule = false; + } + return 0; + case 'n': /* Print, not exec commands */ + if (invert_this) { + do_not_exec_rule = false; + } else { + do_not_exec_rule = true; + } + return 0; +#ifndef PARALLEL + case 'O': /* Send job start & result msgs */ + if (invert_this) { + send_mtool_msgs = false; + } else { +#ifdef DISTRIBUTED + send_mtool_msgs = true; +#endif + } + return 128; +#endif + case 'o': /* Use alternative dmake output dir */ + if (invert_this) { + dmake_odir_specified = false; + } else { + dmake_odir_specified = true; + } + return 512; + case 'P': /* Print for selected targets */ + if (invert_this) { + report_dependencies_level--; + } else { + report_dependencies_level++; + } + return 0; + case 'p': /* Print description */ + if (invert_this) { + trace_status = false; + do_not_exec_rule = false; + } else { + trace_status = true; + do_not_exec_rule = true; + } + return 0; + case 'q': /* Question flag */ + if (invert_this) { + quest = false; + } else { + quest = true; + } + return 0; + case 'R': /* Don't run in parallel */ +#ifdef TEAMWARE_MAKE_CMN + if (invert_this) { + pmake_cap_r_specified = false; + no_parallel = false; + } else { + pmake_cap_r_specified = true; + dmake_mode_type = serial_mode; + no_parallel = true; + } +#else + warning(catgets(catd, 1, 182, "Ignoring ParallelMake -R option")); +#endif + return 0; + case 'r': /* Turn off internal rules */ + if (invert_this) { + ignore_default_mk = false; + } else { + ignore_default_mk = true; + } + return 0; + case 'S': /* Reverse -k */ + if (invert_this) { + continue_after_error = true; + } else { + continue_after_error = false; + stop_after_error_ever_seen = true; + } + return 0; + case 's': /* Silent flag */ + if (invert_this) { + silent_all = false; + } else { + silent_all = true; + } + return 0; + case 'T': /* Print target list */ + if (invert_this) { + list_all_targets = false; + do_not_exec_rule = false; + } else { + list_all_targets = true; + do_not_exec_rule = true; + } + return 0; + case 't': /* Touch flag */ + if (invert_this) { + touch = false; + } else { + touch = true; + } + return 0; + case 'u': /* Unconditional flag */ + if (invert_this) { + build_unconditional = false; + } else { + build_unconditional = true; + } + return 0; + case 'V': /* SVR4 mode */ + svr4 = true; + return 0; + case 'v': /* Version flag */ + if (invert_this) { + } else { +#ifdef TEAMWARE_MAKE_CMN + fprintf(stdout, NOCATGETS("dmake: %s\n"), verstring); +#ifdef SUN5_0 + exit_status = 0; +#endif + exit(0); +#else + warning(catgets(catd, 1, 324, "Ignoring DistributedMake -v option")); +#endif + } + return 0; + case 'w': /* Unconditional flag */ + if (invert_this) { + report_cwd = false; + } else { + report_cwd = true; + } + return 0; +#if 0 + case 'X': /* Filter stdout */ + if (invert_this) { + filter_stderr = false; + } else { + filter_stderr = true; + } + return 0; +#endif + default: + break; + } + return 0; +} + +/* + * setup_for_projectdir() + * + * Read the PROJECTDIR variable, if defined, and set the sccs path + * + * Parameters: + * + * Global variables used: + * sccs_dir_path Set to point to SCCS dir to use + */ +static void +setup_for_projectdir(void) +{ +static char path[MAXPATHLEN]; +char cwdpath[MAXPATHLEN]; +uid_t uid; +int done=0; + + /* Check if we should use PROJECTDIR when reading the SCCS dir. */ + sccs_dir_path = getenv(NOCATGETS("PROJECTDIR")); + if ((sccs_dir_path != NULL) && + (sccs_dir_path[0] != (int) slash_char)) { + struct passwd *pwent; + + { + uid = getuid(); + pwent = getpwuid(uid); + if (pwent == NULL) { + fatal(catgets(catd, 1, 188, "Bogus USERID ")); + } + if ((pwent = getpwnam(sccs_dir_path)) == NULL) { + /*empty block : it'll go & check cwd */ + } + else { + (void) sprintf(path, NOCATGETS("%s/src"), pwent->pw_dir); + if (access(path, F_OK) == 0) { + sccs_dir_path = path; + done = 1; + } else { + (void) sprintf(path, NOCATGETS("%s/source"), pwent->pw_dir); + if (access(path, F_OK) == 0) { + sccs_dir_path = path; + done = 1; + } + } + } + if (!done) { + if (getcwd(cwdpath, MAXPATHLEN - 1 )) { + + (void) sprintf(path, NOCATGETS("%s/%s"), cwdpath,sccs_dir_path); + if (access(path, F_OK) == 0) { + sccs_dir_path = path; + done = 1; + } else { + fatal(catgets(catd, 1, 189, "Bogus PROJECTDIR '%s'"), sccs_dir_path); + } + } + } + } + } +} + +/* + * set_sgs_support() + * + * Add the libmakestate.so.1 lib to the env var SGS_SUPPORT + * if it's not already in there. + * The SGS_SUPPORT env var and libmakestate.so.1 is used by + * the linker ld to report .make.state info back to make. + */ +static void +set_sgs_support() +{ + int len; + char *newpath; + char *oldpath; + static char *prev_path; + + oldpath = getenv(LD_SUPPORT_ENV_VAR); + if (oldpath == NULL) { + len = strlen(LD_SUPPORT_ENV_VAR) + 1 + + strlen(LD_SUPPORT_MAKE_LIB) + 1; + newpath = (char *) malloc(len); + sprintf(newpath, "%s=", LD_SUPPORT_ENV_VAR); + } else { + len = strlen(LD_SUPPORT_ENV_VAR) + 1 + strlen(oldpath) + 1 + + strlen(LD_SUPPORT_MAKE_LIB) + 1; + newpath = (char *) malloc(len); + sprintf(newpath, "%s=%s", LD_SUPPORT_ENV_VAR, oldpath); + } + +#if defined(TEAMWARE_MAKE_CMN) + + /* function maybe_append_str_to_env_var() is defined in avo_util library + * Serial make should not use this library !!! + */ + maybe_append_str_to_env_var(newpath, LD_SUPPORT_MAKE_LIB); +#else + if (oldpath == NULL) { + sprintf(newpath, "%s%s", newpath, LD_SUPPORT_MAKE_LIB); + } else { + sprintf(newpath, "%s:%s", newpath, LD_SUPPORT_MAKE_LIB); + } +#endif + putenv(newpath); + if (prev_path) { + free(prev_path); + } + prev_path = newpath; +} + +/* + * read_files_and_state(argc, argv) + * + * Read the makefiles we care about and the environment + * Also read the = style command line options + * + * Parameters: + * argc You know what this is + * argv You know what this is + * + * Static variables used: + * env_wins make -e, determines if env vars are RO + * ignore_default_mk make -r, determines if make.rules is read + * not_auto_depen dwight + * + * Global variables used: + * default_target_to_build Set to first proper target from file + * do_not_exec_rule Set to false when makfile is made + * dot The Name ".", used to read current dir + * empty_name The Name "", use as macro value + * keep_state Set if KEEP_STATE is in environment + * make_state The Name ".make.state", used to read file + * makefile_type Set to type of file being read + * makeflags The Name "MAKEFLAGS", used to set macro value + * not_auto dwight + * nse Set if NSE_ENV is in the environment + * read_trace_level Checked to se if the reader should trace + * report_dependencies If -P is on we do not read .make.state + * trace_reader Set if reader should trace + * virtual_root The Name "VIRTUAL_ROOT", used to check value + */ +static void +read_files_and_state(int argc, char **argv) +{ + wchar_t buffer[1000]; + wchar_t buffer_posix[1000]; + register char ch; + register char *cp; + Property def_make_macro = NULL; + Name def_make_name; + Name default_makefile; + String_rec dest; + wchar_t destbuffer[STRING_BUFFER_LENGTH]; + register int i; + register int j; + Name keep_state_name; + int length; + Name Makefile; + register Property macro; + struct stat make_state_stat; + Name makefile_name; + register int makefile_next = 0; + register Boolean makefile_read = false; + String_rec makeflags_string; + String_rec makeflags_string_posix; + String_rec * makeflags_string_current; + Name makeflags_value_saved; + register Name name; + Name new_make_value; + Boolean save_do_not_exec_rule; + Name sdotMakefile; + Name sdotmakefile_name; + static wchar_t state_file_str; + static char state_file_str_mb[MAXPATHLEN]; + static struct _Name state_filename; + Boolean temp; + char tmp_char; + wchar_t *tmp_wcs_buffer; + register Name value; + ASCII_Dyn_Array makeflags_and_macro; + Boolean is_xpg4; + +/* + * Remember current mode. It may be changed after reading makefile + * and we will have to correct MAKEFLAGS variable. + */ + is_xpg4 = posix; + + MBSTOWCS(wcs_buffer, NOCATGETS("KEEP_STATE")); + keep_state_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("Makefile")); + Makefile = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("makefile")); + makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("s.makefile")); + sdotmakefile_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("s.Makefile")); + sdotMakefile = GETNAME(wcs_buffer, FIND_LENGTH); + +/* + * Set flag if NSE is active + */ +#ifdef NSE + if (getenv(NOCATGETS("NSE_ENV")) != NULL) { + nse = true; + } +#endif + +/* + * initialize global dependency entry for .NOT_AUTO + */ + not_auto_depen->next = NULL; + not_auto_depen->name = not_auto; + not_auto_depen->automatic = not_auto_depen->stale = false; + +/* + * Read internal definitions and rules. + */ + if (read_trace_level > 1) { + trace_reader = true; + } + if (!ignore_default_mk) { +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + if (svr4) { + MBSTOWCS(wcs_buffer, NOCATGETS("svr4.make.rules")); + default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); + } else { + MBSTOWCS(wcs_buffer, NOCATGETS("make.rules")); + default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); + } +#else + MBSTOWCS(wcs_buffer, NOCATGETS("default.mk")); + default_makefile = GETNAME(wcs_buffer, FIND_LENGTH); +#endif + default_makefile->stat.is_file = true; + + (void) read_makefile(default_makefile, + true, + false, + true); + } + + /* + * If the user did not redefine the MAKE macro in the + * default makefile (make.rules), then we'd like to + * change the macro value of MAKE to be some form + * of argv[0] for recursive MAKE builds. + */ + MBSTOWCS(wcs_buffer, NOCATGETS("MAKE")); + def_make_name = GETNAME(wcs_buffer, wslen(wcs_buffer)); + def_make_macro = get_prop(def_make_name->prop, macro_prop); + if ((def_make_macro != NULL) && + (IS_EQUAL(def_make_macro->body.macro.value->string_mb, + NOCATGETS("make")))) { + MBSTOWCS(wcs_buffer, argv_zero_string); + new_make_value = GETNAME(wcs_buffer, wslen(wcs_buffer)); + (void) SETVAR(def_make_name, + new_make_value, + false); + } + + default_target_to_build = NULL; + trace_reader = false; + +/* + * Read environment args. Let file args which follow override unless + * -e option seen. If -e option is not mentioned. + */ + read_environment(env_wins); + if (getvar(virtual_root)->hash.length == 0) { + maybe_append_prop(virtual_root, macro_prop) + ->body.macro.exported = true; + MBSTOWCS(wcs_buffer, "/"); + (void) SETVAR(virtual_root, + GETNAME(wcs_buffer, FIND_LENGTH), + false); + } + +/* + * We now scan mf_argv and argv to see if we need to set + * any of the DMake-added options/variables in MAKEFLAGS. + */ + + makeflags_and_macro.start = 0; + makeflags_and_macro.size = 0; + enter_argv_values(mf_argc, mf_argv, &makeflags_and_macro); + enter_argv_values(argc, argv, &makeflags_and_macro); + +/* + * Set MFLAGS and MAKEFLAGS + * + * Before reading makefile we do not know exactly which mode + * (posix or not) is used. So prepare two MAKEFLAGS strings + * for both posix and solaris modes because they are different. + */ + INIT_STRING_FROM_STACK(makeflags_string, buffer); + INIT_STRING_FROM_STACK(makeflags_string_posix, buffer_posix); + append_char((int) hyphen_char, &makeflags_string); + append_char((int) hyphen_char, &makeflags_string_posix); + + switch (read_trace_level) { + case 2: + append_char('D', &makeflags_string); + append_char('D', &makeflags_string_posix); + case 1: + append_char('D', &makeflags_string); + append_char('D', &makeflags_string_posix); + } + switch (debug_level) { + case 2: + append_char('d', &makeflags_string); + append_char('d', &makeflags_string_posix); + case 1: + append_char('d', &makeflags_string); + append_char('d', &makeflags_string_posix); + } +#ifdef NSE + if (nse) { + append_char('E', &makeflags_string); + } +#endif + if (env_wins) { + append_char('e', &makeflags_string); + append_char('e', &makeflags_string_posix); + } + if (ignore_errors_all) { + append_char('i', &makeflags_string); + append_char('i', &makeflags_string_posix); + } + if (continue_after_error) { + if (stop_after_error_ever_seen) { + append_char('S', &makeflags_string_posix); + append_char((int) space_char, &makeflags_string_posix); + append_char((int) hyphen_char, &makeflags_string_posix); + } + append_char('k', &makeflags_string); + append_char('k', &makeflags_string_posix); + } else { + if (stop_after_error_ever_seen + && continue_after_error_ever_seen) { + append_char('k', &makeflags_string_posix); + append_char((int) space_char, &makeflags_string_posix); + append_char((int) hyphen_char, &makeflags_string_posix); + append_char('S', &makeflags_string_posix); + } + } + if (do_not_exec_rule) { + append_char('n', &makeflags_string); + append_char('n', &makeflags_string_posix); + } + switch (report_dependencies_level) { + case 4: + append_char('P', &makeflags_string); + append_char('P', &makeflags_string_posix); + case 3: + append_char('P', &makeflags_string); + append_char('P', &makeflags_string_posix); + case 2: + append_char('P', &makeflags_string); + append_char('P', &makeflags_string_posix); + case 1: + append_char('P', &makeflags_string); + append_char('P', &makeflags_string_posix); + } + if (trace_status) { + append_char('p', &makeflags_string); + append_char('p', &makeflags_string_posix); + } + if (quest) { + append_char('q', &makeflags_string); + append_char('q', &makeflags_string_posix); + } + if (silent_all) { + append_char('s', &makeflags_string); + append_char('s', &makeflags_string_posix); + } + if (touch) { + append_char('t', &makeflags_string); + append_char('t', &makeflags_string_posix); + } + if (build_unconditional) { + append_char('u', &makeflags_string); + append_char('u', &makeflags_string_posix); + } + if (report_cwd) { + append_char('w', &makeflags_string); + append_char('w', &makeflags_string_posix); + } +#ifndef PARALLEL + /* -c dmake_rcfile */ + if (dmake_rcfile_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); + dmake_rcfile = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(dmake_rcfile, &makeflags_string); + append_makeflags_string(dmake_rcfile, &makeflags_string_posix); + } + /* -g dmake_group */ + if (dmake_group_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); + dmake_group = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(dmake_group, &makeflags_string); + append_makeflags_string(dmake_group, &makeflags_string_posix); + } + /* -j dmake_max_jobs */ + if (dmake_max_jobs_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); + dmake_max_jobs = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(dmake_max_jobs, &makeflags_string); + append_makeflags_string(dmake_max_jobs, &makeflags_string_posix); + } + /* -m dmake_mode */ + if (dmake_mode_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); + dmake_mode = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(dmake_mode, &makeflags_string); + append_makeflags_string(dmake_mode, &makeflags_string_posix); + } + /* -x dmake_compat_mode */ +// if (dmake_compat_mode_specified) { +// MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE")); +// dmake_compat_mode = GETNAME(wcs_buffer, FIND_LENGTH); +// append_makeflags_string(dmake_compat_mode, &makeflags_string); +// append_makeflags_string(dmake_compat_mode, &makeflags_string_posix); +// } + /* -x dmake_output_mode */ + if (dmake_output_mode_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); + dmake_output_mode = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(dmake_output_mode, &makeflags_string); + append_makeflags_string(dmake_output_mode, &makeflags_string_posix); + } + /* -o dmake_odir */ + if (dmake_odir_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); + dmake_odir = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(dmake_odir, &makeflags_string); + append_makeflags_string(dmake_odir, &makeflags_string_posix); + } + /* -M pmake_machinesfile */ + if (pmake_machinesfile_specified) { + MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); + pmake_machinesfile = GETNAME(wcs_buffer, FIND_LENGTH); + append_makeflags_string(pmake_machinesfile, &makeflags_string); + append_makeflags_string(pmake_machinesfile, &makeflags_string_posix); + } + /* -R */ + if (pmake_cap_r_specified) { + append_char((int) space_char, &makeflags_string); + append_char((int) hyphen_char, &makeflags_string); + append_char('R', &makeflags_string); + append_char((int) space_char, &makeflags_string_posix); + append_char((int) hyphen_char, &makeflags_string_posix); + append_char('R', &makeflags_string_posix); + } +#endif + +/* + * Make sure MAKEFLAGS is exported + */ + maybe_append_prop(makeflags, macro_prop)-> + body.macro.exported = true; + + if (makeflags_string.buffer.start[1] != (int) nul_char) { + if (makeflags_string.buffer.start[1] != (int) space_char) { + MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS")); + (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), + GETNAME(makeflags_string.buffer.start, + FIND_LENGTH), + false); + } else { + MBSTOWCS(wcs_buffer, NOCATGETS("MFLAGS")); + (void) SETVAR(GETNAME(wcs_buffer, FIND_LENGTH), + GETNAME(makeflags_string.buffer.start + 2, + FIND_LENGTH), + false); + } + } + +/* + * Add command line macro to POSIX makeflags_string + */ + if (makeflags_and_macro.start) { + tmp_char = (char) space_char; + cp = makeflags_and_macro.start; + do { + append_char(tmp_char, &makeflags_string_posix); + } while ( tmp_char = *cp++ ); + retmem_mb(makeflags_and_macro.start); + } + +/* + * Now set the value of MAKEFLAGS macro in accordance + * with current mode. + */ + macro = maybe_append_prop(makeflags, macro_prop); + temp = (Boolean) macro->body.macro.read_only; + macro->body.macro.read_only = false; + if(posix || gnu_style) { + makeflags_string_current = &makeflags_string_posix; + } else { + makeflags_string_current = &makeflags_string; + } + if (makeflags_string_current->buffer.start[1] == (int) nul_char) { + makeflags_value_saved = + GETNAME( makeflags_string_current->buffer.start + 1 + , FIND_LENGTH + ); + } else { + if (makeflags_string_current->buffer.start[1] != (int) space_char) { + makeflags_value_saved = + GETNAME( makeflags_string_current->buffer.start + , FIND_LENGTH + ); + } else { + makeflags_value_saved = + GETNAME( makeflags_string_current->buffer.start + 2 + , FIND_LENGTH + ); + } + } + (void) SETVAR( makeflags + , makeflags_value_saved + , false + ); + macro->body.macro.read_only = temp; + +/* + * Read command line "-f" arguments and ignore -c, g, j, K, M, m, O and o args. + */ + save_do_not_exec_rule = do_not_exec_rule; + do_not_exec_rule = false; + if (read_trace_level > 0) { + trace_reader = true; + } + + for (i = 1; i < argc; i++) { + if (argv[i] && + (argv[i][0] == (int) hyphen_char) && + (argv[i][1] == 'f') && + (argv[i][2] == (int) nul_char)) { + argv[i] = NULL; /* Remove -f */ + if (i >= argc - 1) { + fatal(catgets(catd, 1, 190, "No filename argument after -f flag")); + } + MBSTOWCS(wcs_buffer, argv[++i]); + primary_makefile = GETNAME(wcs_buffer, FIND_LENGTH); + (void) read_makefile(primary_makefile, true, true, true); + argv[i] = NULL; /* Remove filename */ + makefile_read = true; + } else if (argv[i] && + (argv[i][0] == (int) hyphen_char) && + (argv[i][1] == 'c' || + argv[i][1] == 'g' || + argv[i][1] == 'j' || + argv[i][1] == 'K' || + argv[i][1] == 'M' || + argv[i][1] == 'm' || + argv[i][1] == 'O' || + argv[i][1] == 'o') && + (argv[i][2] == (int) nul_char)) { + argv[i] = NULL; + argv[++i] = NULL; + } + } + +/* + * If no command line "-f" args then look for "makefile", and then for + * "Makefile" if "makefile" isn't found. + */ + if (!makefile_read) { + (void) read_dir(dot, + (wchar_t *) NULL, + (Property) NULL, + (wchar_t *) NULL); + if (!posix) { + if (makefile_name->stat.is_file) { + if (Makefile->stat.is_file) { + warning(catgets(catd, 1, 310, "Both `makefile' and `Makefile' exist")); + } + primary_makefile = makefile_name; + makefile_read = read_makefile(makefile_name, + false, + false, + true); + } + if (!makefile_read && + Makefile->stat.is_file) { + primary_makefile = Makefile; + makefile_read = read_makefile(Makefile, + false, + false, + true); + } + } else { + + enum sccs_stat save_m_has_sccs = NO_SCCS; + enum sccs_stat save_M_has_sccs = NO_SCCS; + + if (makefile_name->stat.is_file) { + if (Makefile->stat.is_file) { + warning(catgets(catd, 1, 191, "Both `makefile' and `Makefile' exist")); + } + } + if (makefile_name->stat.is_file) { + if (makefile_name->stat.has_sccs == NO_SCCS) { + primary_makefile = makefile_name; + makefile_read = read_makefile(makefile_name, + false, + false, + true); + } else { + save_m_has_sccs = makefile_name->stat.has_sccs; + makefile_name->stat.has_sccs = NO_SCCS; + primary_makefile = makefile_name; + makefile_read = read_makefile(makefile_name, + false, + false, + true); + } + } + if (!makefile_read && + Makefile->stat.is_file) { + if (Makefile->stat.has_sccs == NO_SCCS) { + primary_makefile = Makefile; + makefile_read = read_makefile(Makefile, + false, + false, + true); + } else { + save_M_has_sccs = Makefile->stat.has_sccs; + Makefile->stat.has_sccs = NO_SCCS; + primary_makefile = Makefile; + makefile_read = read_makefile(Makefile, + false, + false, + true); + } + } + if (!makefile_read && + makefile_name->stat.is_file) { + makefile_name->stat.has_sccs = save_m_has_sccs; + primary_makefile = makefile_name; + makefile_read = read_makefile(makefile_name, + false, + false, + true); + } + if (!makefile_read && + Makefile->stat.is_file) { + Makefile->stat.has_sccs = save_M_has_sccs; + primary_makefile = Makefile; + makefile_read = read_makefile(Makefile, + false, + false, + true); + } + } + } + do_not_exec_rule = save_do_not_exec_rule; + allrules_read = makefile_read; + trace_reader = false; + +/* + * Now get current value of MAKEFLAGS and compare it with + * the saved value we set before reading makefile. + * If they are different then MAKEFLAGS is subsequently set by + * makefile, just leave it there. Otherwise, if make mode + * is changed by using .POSIX target in makefile we need + * to correct MAKEFLAGS value. + */ + Name mf_val = getvar(makeflags); + if( (posix != is_xpg4) + && (!strcmp(mf_val->string_mb, makeflags_value_saved->string_mb))) + { + if (makeflags_string_posix.buffer.start[1] == (int) nul_char) { + (void) SETVAR(makeflags, + GETNAME(makeflags_string_posix.buffer.start + 1, + FIND_LENGTH), + false); + } else { + if (makeflags_string_posix.buffer.start[1] != (int) space_char) { + (void) SETVAR(makeflags, + GETNAME(makeflags_string_posix.buffer.start, + FIND_LENGTH), + false); + } else { + (void) SETVAR(makeflags, + GETNAME(makeflags_string_posix.buffer.start + 2, + FIND_LENGTH), + false); + } + } + } + + if (makeflags_string.free_after_use) { + retmem(makeflags_string.buffer.start); + } + if (makeflags_string_posix.free_after_use) { + retmem(makeflags_string_posix.buffer.start); + } + makeflags_string.buffer.start = NULL; + makeflags_string_posix.buffer.start = NULL; + + if (posix) { + /* + * If the user did not redefine the ARFLAGS macro in the + * default makefile (make.rules), then we'd like to + * change the macro value of ARFLAGS to be in accordance + * with "POSIX" requirements. + */ + MBSTOWCS(wcs_buffer, NOCATGETS("ARFLAGS")); + name = GETNAME(wcs_buffer, wslen(wcs_buffer)); + macro = get_prop(name->prop, macro_prop); + if ((macro != NULL) && /* Maybe (macro == NULL) || ? */ + (IS_EQUAL(macro->body.macro.value->string_mb, + NOCATGETS("rv")))) { + MBSTOWCS(wcs_buffer, NOCATGETS("-rv")); + value = GETNAME(wcs_buffer, wslen(wcs_buffer)); + (void) SETVAR(name, + value, + false); + } + } + + if (!posix && !svr4) { + set_sgs_support(); + } + + +/* + * Make sure KEEP_STATE is in the environment if KEEP_STATE is on. + */ + macro = get_prop(keep_state_name->prop, macro_prop); + if ((macro != NULL) && + macro->body.macro.exported) { + keep_state = true; + } + if (keep_state) { + if (macro == NULL) { + macro = maybe_append_prop(keep_state_name, + macro_prop); + } + macro->body.macro.exported = true; + (void) SETVAR(keep_state_name, + empty_name, + false); + + /* + * Read state file + */ + + /* Before we read state, let's make sure we have + ** right state file. + */ + /* just in case macro references are used in make_state file + ** name, we better expand them at this stage using expand_value. + */ + INIT_STRING_FROM_STACK(dest, destbuffer); + expand_value(make_state, &dest, false); + + make_state = GETNAME(dest.buffer.start, FIND_LENGTH); + + if(!stat(make_state->string_mb, &make_state_stat)) { + if(!(make_state_stat.st_mode & S_IFREG) ) { + /* copy the make_state structure to the other + ** and then let make_state point to the new + ** one. + */ + memcpy(&state_filename, make_state,sizeof(state_filename)); + state_filename.string_mb = state_file_str_mb; + /* Just a kludge to avoid two slashes back to back */ + if((make_state->hash.length == 1)&& + (make_state->string_mb[0] == '/')) { + make_state->hash.length = 0; + make_state->string_mb[0] = '\0'; + } + sprintf(state_file_str_mb,NOCATGETS("%s%s"), + make_state->string_mb,NOCATGETS("/.make.state")); + make_state = &state_filename; + /* adjust the length to reflect the appended string */ + make_state->hash.length += 12; + } + } else { /* the file doesn't exist or no permission */ + char tmp_path[MAXPATHLEN]; + char *slashp; + + if (slashp = strrchr(make_state->string_mb, '/')) { + strncpy(tmp_path, make_state->string_mb, + (slashp - make_state->string_mb)); + tmp_path[slashp - make_state->string_mb]=0; + if(strlen(tmp_path)) { + if(stat(tmp_path, &make_state_stat)) { + warning(catgets(catd, 1, 192, "directory %s for .KEEP_STATE_FILE does not exist"),tmp_path); + } + if (access(tmp_path, F_OK) != 0) { + warning(catgets(catd, 1, 193, "can't access dir %s"),tmp_path); + } + } + } + } + if (report_dependencies_level != 1) { + Makefile_type makefile_type_temp = makefile_type; + makefile_type = reading_statefile; + if (read_trace_level > 1) { + trace_reader = true; + } + (void) read_simple_file(make_state, + false, + false, + false, + false, + false, + true); + trace_reader = false; + makefile_type = makefile_type_temp; + } + } +} + +/* + * Scan the argv for options and "=" type args and make them readonly. + */ +static void +enter_argv_values(int argc, char *argv[], ASCII_Dyn_Array *makeflags_and_macro) +{ + register char *cp; + register int i; + int length; + register Name name; + int opt_separator = argc; + char tmp_char; + wchar_t *tmp_wcs_buffer; + register Name value; + Boolean append = false; + Property macro; + struct stat statbuf; + + + /* Read argv options and "=" type args and make them readonly. */ + makefile_type = reading_nothing; + for (i = 1; i < argc; ++i) { + append = false; + if (argv[i] == NULL) { + continue; + } else if (((argv[i][0] == '-') && (argv[i][1] == '-')) || + ((argv[i][0] == (int) ' ') && + (argv[i][1] == (int) '-') && + (argv[i][2] == (int) ' ') && + (argv[i][3] == (int) '-'))) { + argv[i] = NULL; + opt_separator = i; + continue; + } else if ((i < opt_separator) && (argv[i][0] == (int) hyphen_char)) { + switch (parse_command_option(argv[i][1])) { + case 1: /* -f seen */ + ++i; + continue; + case 2: /* -c seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 194, "No dmake rcfile argument after -c flag")); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_RCFILE")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + break; + case 4: /* -g seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 195, "No dmake group argument after -g flag")); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_GROUP")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + break; + case 8: /* -j seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 196, "No dmake max jobs argument after -j flag")); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + break; + case 16: /* -M seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 323, "No pmake machinesfile argument after -M flag")); + } + MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + break; + case 32: /* -m seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 197, "No dmake mode argument after -m flag")); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MODE")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + break; + case 128: /* -O seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 287, "No file descriptor argument after -O flag")); + } + mtool_msgs_fd = atoi(argv[i+1]); + /* find out if mtool_msgs_fd is a valid file descriptor */ + if (fstat(mtool_msgs_fd, &statbuf) < 0) { + fatal(catgets(catd, 1, 355, "Invalid file descriptor %d after -O flag"), mtool_msgs_fd); + } + argv[i] = NULL; + argv[i+1] = NULL; + continue; + case 256: /* -K seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 288, "No makestate filename argument after -K flag")); + } + MBSTOWCS(wcs_buffer, argv[i+1]); + make_state = GETNAME(wcs_buffer, FIND_LENGTH); + keep_state = true; + argv[i] = NULL; + argv[i+1] = NULL; + continue; + case 512: /* -o seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 312, "No dmake output dir argument after -o flag")); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + break; + case 1024: /* -x seen */ + if (argv[i+1] == NULL) { + fatal(catgets(catd, 1, 351, "No argument after -x flag")); + } + length = strlen( NOCATGETS("SUN_MAKE_COMPAT_MODE=")); + if (strncmp(argv[i+1], NOCATGETS("SUN_MAKE_COMPAT_MODE="), length) == 0) { + argv[i+1] = &argv[i+1][length]; + MBSTOWCS(wcs_buffer, NOCATGETS("SUN_MAKE_COMPAT_MODE")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + dmake_compat_mode_specified = dmake_add_mode_specified; + break; + } + length = strlen( NOCATGETS("DMAKE_OUTPUT_MODE=")); + if (strncmp(argv[i+1], NOCATGETS("DMAKE_OUTPUT_MODE="), length) == 0) { + argv[i+1] = &argv[i+1][length]; + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_OUTPUT_MODE")); + name = GETNAME(wcs_buffer, FIND_LENGTH); + dmake_output_mode_specified = dmake_add_mode_specified; + } else { + warning(catgets(catd, 1, 354, "Unknown argument `%s' after -x flag (ignored)"), + argv[i+1]); + argv[i] = argv[i + 1] = NULL; + continue; + } + break; + default: /* Shouldn't reach here */ + argv[i] = NULL; + continue; + } + argv[i] = NULL; + if (i == (argc - 1)) { + break; + } + if ((length = strlen(argv[i+1])) >= MAXPATHLEN) { + tmp_wcs_buffer = ALLOC_WC(length + 1); + (void) mbstowcs(tmp_wcs_buffer, argv[i+1], length + 1); + value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); + retmem(tmp_wcs_buffer); + } else { + MBSTOWCS(wcs_buffer, argv[i+1]); + value = GETNAME(wcs_buffer, FIND_LENGTH); + } + argv[i+1] = NULL; + } else if ((cp = strchr(argv[i], (int) equal_char)) != NULL) { +/* + * Combine all macro in dynamic array + */ + if(*(cp-1) == (int) plus_char) + { + if(isspace(*(cp-2))) { + append = true; + cp--; + } + } + if(!append) + append_or_replace_macro_in_dyn_array(makeflags_and_macro, argv[i]); + + while (isspace(*(cp-1))) { + cp--; + } + tmp_char = *cp; + *cp = (int) nul_char; + MBSTOWCS(wcs_buffer, argv[i]); + *cp = tmp_char; + name = GETNAME(wcs_buffer, wslen(wcs_buffer)); + while (*cp != (int) equal_char) { + cp++; + } + cp++; + while (isspace(*cp) && (*cp != (int) nul_char)) { + cp++; + } + if ((length = strlen(cp)) >= MAXPATHLEN) { + tmp_wcs_buffer = ALLOC_WC(length + 1); + (void) mbstowcs(tmp_wcs_buffer, cp, length + 1); + value = GETNAME(tmp_wcs_buffer, FIND_LENGTH); + retmem(tmp_wcs_buffer); + } else { + MBSTOWCS(wcs_buffer, cp); + value = GETNAME(wcs_buffer, FIND_LENGTH); + } + argv[i] = NULL; + } else { + /* Illegal MAKEFLAGS argument */ + continue; + } + if(append) { + setvar_append(name, value); + append = false; + } else { + macro = maybe_append_prop(name, macro_prop); + macro->body.macro.exported = true; + SETVAR(name, value, false)->body.macro.read_only = true; + } + } +} + +/* + * Append the DMake option and value to the MAKEFLAGS string. + */ +static void +append_makeflags_string(Name name, register String makeflags_string) +{ + char *option; + + if (strcmp(name->string_mb, NOCATGETS("DMAKE_GROUP")) == 0) { + option = NOCATGETS(" -g "); + } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MAX_JOBS")) == 0) { + option = NOCATGETS(" -j "); + } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_MODE")) == 0) { + option = NOCATGETS(" -m "); + } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_ODIR")) == 0) { + option = NOCATGETS(" -o "); + } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_RCFILE")) == 0) { + option = NOCATGETS(" -c "); + } else if (strcmp(name->string_mb, NOCATGETS("PMAKE_MACHINESFILE")) == 0) { + option = NOCATGETS(" -M "); + } else if (strcmp(name->string_mb, NOCATGETS("DMAKE_OUTPUT_MODE")) == 0) { + option = NOCATGETS(" -x DMAKE_OUTPUT_MODE="); + } else if (strcmp(name->string_mb, NOCATGETS("SUN_MAKE_COMPAT_MODE")) == 0) { + option = NOCATGETS(" -x SUN_MAKE_COMPAT_MODE="); + } else { + fatal(catgets(catd, 1, 289, "Internal error: name not recognized in append_makeflags_string()")); + } + Property prop = maybe_append_prop(name, macro_prop); + if( prop == 0 || prop->body.macro.value == 0 || + prop->body.macro.value->string_mb == 0 ) { + return; + } + char mbs_value[MAXPATHLEN + 100]; + strcpy(mbs_value, option); + strcat(mbs_value, prop->body.macro.value->string_mb); + MBSTOWCS(wcs_buffer, mbs_value); + append_string(wcs_buffer, makeflags_string, FIND_LENGTH); +} + +/* + * read_environment(read_only) + * + * This routine reads the process environment when make starts and enters + * it as make macros. The environment variable SHELL is ignored. + * + * Parameters: + * read_only Should we make env vars read only? + * + * Global variables used: + * report_pwd Set if this make was started by other make + */ +static void +read_environment(Boolean read_only) +{ + register char **environment; + int length; + wchar_t *tmp_wcs_buffer; + Boolean alloced_tmp_wcs_buffer = false; + register wchar_t *name; + register wchar_t *value; + register Name macro; + Property val; + Boolean read_only_saved; + + reading_environment = true; + environment = environ; + for (; *environment; environment++) { + read_only_saved = read_only; + if ((length = strlen(*environment)) >= MAXPATHLEN) { + tmp_wcs_buffer = ALLOC_WC(length + 1); + alloced_tmp_wcs_buffer = true; + (void) mbstowcs(tmp_wcs_buffer, *environment, length + 1); + name = tmp_wcs_buffer; + } else { + MBSTOWCS(wcs_buffer, *environment); + name = wcs_buffer; + } + value = (wchar_t *) wschr(name, (int) equal_char); + + /* + * Looks like there's a bug in the system, but sometimes + * you can get blank lines in *environment. + */ + if (!value) { + continue; + } + MBSTOWCS(wcs_buffer2, NOCATGETS("SHELL=")); + if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { + continue; + } + MBSTOWCS(wcs_buffer2, NOCATGETS("MAKEFLAGS=")); + if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { + report_pwd = true; + /* + * In POSIX mode we do not want MAKEFLAGS to be readonly. + * If the MAKEFLAGS macro is subsequently set by the makefile, + * it replaces the MAKEFLAGS variable currently found in the + * environment. + * See Assertion 50 in section 6.2.5.3 of standard P1003.3.2/D8. + */ + if(posix) { + read_only_saved = false; + } + } + + /* + * We ignore SUNPRO_DEPENDENCIES and NSE_DEP. Those + * environment variables are set by make and read by + * cpp which then writes info to .make.dependency.xxx and + * .nse_depinfo. When make is invoked by another make + * (recursive make), we don't want to read this because + * then the child make will end up writing to the parent + * directory's .make.state and .nse_depinfo and clobbering + * them. + */ + MBSTOWCS(wcs_buffer2, NOCATGETS("SUNPRO_DEPENDENCIES")); + if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { + continue; + } +#ifdef NSE + MBSTOWCS(wcs_buffer2, NOCATGETS("NSE_DEP")); + if (IS_WEQUALN(name, wcs_buffer2, wslen(wcs_buffer2))) { + continue; + } +#endif + + macro = GETNAME(name, value - name); + maybe_append_prop(macro, macro_prop)->body.macro.exported = + true; + if ((value == NULL) || ((value + 1)[0] == (int) nul_char)) { + val = setvar_daemon(macro, + (Name) NULL, + false, no_daemon, false, debug_level); + } else { + val = setvar_daemon(macro, + GETNAME(value + 1, FIND_LENGTH), + false, no_daemon, false, debug_level); + } +#ifdef NSE + /* + * Must be after the call to setvar() as it sets + * imported to false. + */ + maybe_append_prop(macro, macro_prop)->body.macro.imported = true; +#endif + val->body.macro.read_only = read_only_saved; + if (alloced_tmp_wcs_buffer) { + retmem(tmp_wcs_buffer); + alloced_tmp_wcs_buffer = false; + } + } + reading_environment = false; +} + +/* + * read_makefile(makefile, complain, must_exist, report_file) + * + * Read one makefile and check the result + * + * Return value: + * false is the read failed + * + * Parameters: + * makefile The file to read + * complain Passed thru to read_simple_file() + * must_exist Passed thru to read_simple_file() + * report_file Passed thru to read_simple_file() + * + * Global variables used: + * makefile_type Set to indicate we are reading main file + * recursion_level Initialized + */ +static Boolean +read_makefile(register Name makefile, Boolean complain, Boolean must_exist, Boolean report_file) +{ + Boolean b; + + makefile_type = reading_makefile; + recursion_level = 0; +#ifdef NSE + wscpy(current_makefile, makefile->string); +#endif + reading_dependencies = true; + b = read_simple_file(makefile, true, true, complain, + must_exist, report_file, false); + reading_dependencies = false; + return b; +} + +/* + * make_targets(argc, argv, parallel_flag) + * + * Call doname on the specified targets + * + * Parameters: + * argc You know what this is + * argv You know what this is + * parallel_flag True if building in parallel + * + * Global variables used: + * build_failed_seen Used to generated message after failed -k + * commands_done Used to generate message "Up to date" + * default_target_to_build First proper target in makefile + * init The Name ".INIT", use to run command + * parallel Global parallel building flag + * quest make -q, suppresses messages + * recursion_level Initialized, used for tracing + * report_dependencies make -P, regroves whole process + */ +static void +make_targets(int argc, char **argv, Boolean parallel_flag) +{ + int i; + char *cp; + Doname result; + register Boolean target_to_make_found = false; + + (void) doname(init, true, true); + recursion_level = 1; + parallel = parallel_flag; +/* + * make remaining args + */ +#ifdef TEAMWARE_MAKE_CMN +/* + if ((report_dependencies_level == 0) && parallel) { + */ + if (parallel) { + /* + * If building targets in parallel, start all of the + * remaining args to build in parallel. + */ + for (i = 1; i < argc; i++) { + if ((cp = argv[i]) != NULL) { + commands_done = false; + if ((cp[0] == (int) period_char) && + (cp[1] == (int) slash_char)) { + cp += 2; + } + if((cp[0] == (int) ' ') && + (cp[1] == (int) '-') && + (cp[2] == (int) ' ') && + (cp[3] == (int) '-')) { + argv[i] = NULL; + continue; + } + MBSTOWCS(wcs_buffer, cp); + //default_target_to_build = GETNAME(wcs_buffer, + // FIND_LENGTH); + default_target_to_build = normalize_name(wcs_buffer, + wslen(wcs_buffer)); + if (default_target_to_build == wait_name) { + if (parallel_process_cnt > 0) { + finish_running(); + } + continue; + } + top_level_target = get_wstring(default_target_to_build->string_mb); + /* + * If we can't execute the current target in + * parallel, hold off the target processing + * to preserve the order of the targets as they appeared + * in command line. + */ + if (!parallel_ok(default_target_to_build, false) + && parallel_process_cnt > 0) { + finish_running(); + } + result = doname_check(default_target_to_build, + true, + false, + false); + gather_recursive_deps(); + if (/* !commands_done && */ + (result == build_ok) && + !quest && + (report_dependencies_level == 0) /* && + (exists(default_target_to_build) > file_doesnt_exist) */) { + if (posix) { + if (!commands_done) { + (void) printf(catgets(catd, 1, 293, "`%s' is updated.\n"), + default_target_to_build->string_mb); + } else { + if (no_action_was_taken) { + (void) printf(catgets(catd, 1, 294, "`%s': no action was taken.\n"), + default_target_to_build->string_mb); + } + } + } else { + default_target_to_build->stat.time = file_no_time; + if (!commands_done && + (exists(default_target_to_build) > file_doesnt_exist)) { + (void) printf(catgets(catd, 1, 295, "`%s' is up to date.\n"), + default_target_to_build->string_mb); + } + } + } + } + } + /* Now wait for all of the targets to finish running */ + finish_running(); + // setjmp(jmpbuffer); + + } +#endif + for (i = 1; i < argc; i++) { + if ((cp = argv[i]) != NULL) { + target_to_make_found = true; + if ((cp[0] == (int) period_char) && + (cp[1] == (int) slash_char)) { + cp += 2; + } + if((cp[0] == (int) ' ') && + (cp[1] == (int) '-') && + (cp[2] == (int) ' ') && + (cp[3] == (int) '-')) { + argv[i] = NULL; + continue; + } + MBSTOWCS(wcs_buffer, cp); + default_target_to_build = normalize_name(wcs_buffer, wslen(wcs_buffer)); + top_level_target = get_wstring(default_target_to_build->string_mb); + report_recursion(default_target_to_build); + commands_done = false; + if (parallel) { + result = (Doname) default_target_to_build->state; + } else { + result = doname_check(default_target_to_build, + true, + false, + false); + } + gather_recursive_deps(); + if (build_failed_seen) { + build_failed_ever_seen = true; + warning(catgets(catd, 1, 200, "Target `%s' not remade because of errors"), + default_target_to_build->string_mb); + } + build_failed_seen = false; + if (report_dependencies_level > 0) { + print_dependencies(default_target_to_build, + get_prop(default_target_to_build->prop, + line_prop)); + } + default_target_to_build->stat.time = + file_no_time; + if (default_target_to_build->colon_splits > 0) { + default_target_to_build->state = + build_dont_know; + } + if (!parallel && + /* !commands_done && */ + (result == build_ok) && + !quest && + (report_dependencies_level == 0) /* && + (exists(default_target_to_build) > file_doesnt_exist) */) { + if (posix) { + if (!commands_done) { + (void) printf(catgets(catd, 1, 296, "`%s' is updated.\n"), + default_target_to_build->string_mb); + } else { + if (no_action_was_taken) { + (void) printf(catgets(catd, 1, 297, "`%s': no action was taken.\n"), + default_target_to_build->string_mb); + } + } + } else { + if (!commands_done && + (exists(default_target_to_build) > file_doesnt_exist)) { + (void) printf(catgets(catd, 1, 298, "`%s' is up to date.\n"), + default_target_to_build->string_mb); + } + } + } + } + } + +/* + * If no file arguments have been encountered, + * make the first name encountered that doesnt start with a dot + */ + if (!target_to_make_found) { + if (default_target_to_build == NULL) { + fatal(catgets(catd, 1, 202, "No arguments to build")); + } + commands_done = false; + top_level_target = get_wstring(default_target_to_build->string_mb); + report_recursion(default_target_to_build); + + + if (getenv(NOCATGETS("SPRO_EXPAND_ERRORS"))){ + (void) printf(NOCATGETS("::(%s)\n"), + default_target_to_build->string_mb); + } + + +#ifdef TEAMWARE_MAKE_CMN + result = doname_parallel(default_target_to_build, true, false); +#else + result = doname_check(default_target_to_build, true, + false, false); +#endif + gather_recursive_deps(); + if (build_failed_seen) { + build_failed_ever_seen = true; + warning(catgets(catd, 1, 203, "Target `%s' not remade because of errors"), + default_target_to_build->string_mb); + } + build_failed_seen = false; + if (report_dependencies_level > 0) { + print_dependencies(default_target_to_build, + get_prop(default_target_to_build-> + prop, + line_prop)); + } + default_target_to_build->stat.time = file_no_time; + if (default_target_to_build->colon_splits > 0) { + default_target_to_build->state = build_dont_know; + } + if (/* !commands_done && */ + (result == build_ok) && + !quest && + (report_dependencies_level == 0) /* && + (exists(default_target_to_build) > file_doesnt_exist) */) { + if (posix) { + if (!commands_done) { + (void) printf(catgets(catd, 1, 299, "`%s' is updated.\n"), + default_target_to_build->string_mb); + } else { + if (no_action_was_taken) { + (void) printf(catgets(catd, 1, 300, "`%s': no action was taken.\n"), + default_target_to_build->string_mb); + } + } + } else { + if (!commands_done && + (exists(default_target_to_build) > file_doesnt_exist)) { + (void) printf(catgets(catd, 1, 301, "`%s' is up to date.\n"), + default_target_to_build->string_mb); + } + } + } + } +} + +/* + * report_recursion(target) + * + * If this is a recursive make and the parent make has KEEP_STATE on + * this routine reports the dependency to the parent make + * + * Parameters: + * target Target to report + * + * Global variables used: + * makefiles_used List of makefiles read + * recursive_name The Name ".RECURSIVE", printed + * report_dependency dwight + */ +static void +report_recursion(register Name target) +{ + register FILE *report_file = get_report_file(); + + if ((report_file == NULL) || (report_file == (FILE*)-1)) { + return; + } + if (primary_makefile == NULL) { + /* + * This can happen when there is no makefile and + * only implicit rules are being used. + */ +#ifdef NSE + nse_no_makefile(target); +#endif + return; + } + (void) fprintf(report_file, + "%s: %s ", + get_target_being_reported_for(), + recursive_name->string_mb); + report_dependency(get_current_path()); + report_dependency(target->string_mb); + report_dependency(primary_makefile->string_mb); + (void) fprintf(report_file, "\n"); +} + +/* Next function "append_or_replace_macro_in_dyn_array" must be in "misc.cc". */ +/* NIKMOL */ +extern void +append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro) +{ + register char *cp0; /* work pointer in macro */ + register char *cp1; /* work pointer in array */ + register char *cp2; /* work pointer in array */ + register char *cp3; /* work pointer in array */ + register char *name; /* macro name */ + register char *value; /* macro value */ + register int len_array; + register int len_macro; + + char * esc_value = NULL; + int esc_len; + + if (!(len_macro = strlen(macro))) return; + name = macro; + while (isspace(*(name))) { + name++; + } + if (!(value = strchr(name, (int) equal_char))) { + /* no '=' in macro */ + goto ERROR_MACRO; + } + cp0 = value; + value++; + while (isspace(*(value))) { + value++; + } + while (isspace(*(cp0-1))) { + cp0--; + } + if (cp0 <= name) goto ERROR_MACRO; /* no name */ + if (!(Ar->size)) goto ALLOC_ARRAY; + cp1 = Ar->start; + +LOOK_FOR_NAME: + if (!(cp1 = strchr(cp1, name[0]))) goto APPEND_MACRO; + if (!(cp2 = strchr(cp1, (int) equal_char))) goto APPEND_MACRO; + if (strncmp(cp1, name, (size_t)(cp0-name))) { + /* another name */ + cp1++; + goto LOOK_FOR_NAME; + } + if (cp1 != Ar->start) { + if (!isspace(*(cp1-1))) { + /* another name */ + cp1++; + goto LOOK_FOR_NAME; + } + } + for (cp3 = cp1 + (cp0-name); cp3 < cp2; cp3++) { + if (isspace(*cp3)) continue; + /* else: another name */ + cp1++; + goto LOOK_FOR_NAME; + } + /* Look for the next macro name in array */ + cp3 = cp2+1; + if (*cp3 != (int) doublequote_char) { + /* internal error */ + goto ERROR_MACRO; + } + if (!(cp3 = strchr(cp3+1, (int) doublequote_char))) { + /* internal error */ + goto ERROR_MACRO; + } + cp3++; + while (isspace(*cp3)) { + cp3++; + } + + cp2 = cp1; /* remove old macro */ + if ((*cp3) && (cp3 < Ar->start + Ar->size)) { + for (; cp3 < Ar->start + Ar->size; cp3++) { + *cp2++ = *cp3; + } + } + for (; cp2 < Ar->start + Ar->size; cp2++) { + *cp2 = 0; + } + if (*cp1) { + /* check next name */ + goto LOOK_FOR_NAME; + } + goto APPEND_MACRO; + +ALLOC_ARRAY: + if (Ar->size) { + cp1 = Ar->start; + } else { + cp1 = 0; + } + Ar->size += 128; + Ar->start = getmem(Ar->size); + for (len_array=0; len_array < Ar->size; len_array++) { + Ar->start[len_array] = 0; + } + if (cp1) { + strcpy(Ar->start, cp1); + retmem((wchar_t *) cp1); + } + +APPEND_MACRO: + len_array = strlen(Ar->start); + esc_value = (char*)malloc(strlen(value)*2 + 1); + quote_str(value, esc_value); + esc_len = strlen(esc_value) - strlen(value); + if (len_array + len_macro + esc_len + 5 >= Ar->size) goto ALLOC_ARRAY; + strcat(Ar->start, " "); + strncat(Ar->start, name, cp0-name); + strcat(Ar->start, "="); + strncat(Ar->start, esc_value, strlen(esc_value)); + free(esc_value); + return; +ERROR_MACRO: + /* Macro without '=' or with invalid left/right part */ + return; +} + +#ifdef TEAMWARE_MAKE_CMN +/* + * This function, if registered w/ avo_cli_get_license(), will be called + * if the application is about to exit because: + * 1) there has been certain unrecoverable error(s) that cause the + * application to exit immediately. + * 2) the user has lost a license while the application is running. + */ +extern "C" void +dmake_exit_callback(void) +{ + fatal(catgets(catd, 1, 306, "can not get a license, exiting...")); + exit(1); +} + +/* + * This function, if registered w/ avo_cli_get_license(), will be called + * if the application can not get a license. + */ +extern "C" void +dmake_message_callback(char *err_msg) +{ + static Boolean first = true; + + if (!first) { + return; + } + first = false; + if ((!list_all_targets) && + (report_dependencies_level == 0) && + (dmake_mode_type != serial_mode)) { + warning(catgets(catd, 1, 313, "can not get a TeamWare license, defaulting to serial mode...")); + } +} +#endif + +#ifdef DISTRIBUTED +/* + * Returns whether -c is set or not. + */ +Boolean +get_dmake_rcfile_specified(void) +{ + return(dmake_rcfile_specified); +} + +/* + * Returns whether -g is set or not. + */ +Boolean +get_dmake_group_specified(void) +{ + return(dmake_group_specified); +} + +/* + * Returns whether -j is set or not. + */ +Boolean +get_dmake_max_jobs_specified(void) +{ + return(dmake_max_jobs_specified); +} + +/* + * Returns whether -m is set or not. + */ +Boolean +get_dmake_mode_specified(void) +{ + return(dmake_mode_specified); +} + +/* + * Returns whether -o is set or not. + */ +Boolean +get_dmake_odir_specified(void) +{ + return(dmake_odir_specified); +} + +#endif + +static void +report_dir_enter_leave(Boolean entering) +{ + char rcwd[MAXPATHLEN]; +static char * mlev = NULL; + char * make_level_str = NULL; + int make_level_val = 0; + + make_level_str = getenv(NOCATGETS("MAKELEVEL")); + if(make_level_str) { + make_level_val = atoi(make_level_str); + } + if(mlev == NULL) { + mlev = (char*) malloc(MAXPATHLEN); + } + if(entering) { + sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val + 1); + } else { + make_level_val--; + sprintf(mlev, NOCATGETS("MAKELEVEL=%d"), make_level_val); + } + putenv(mlev); + + if(report_cwd) { + if(make_level_val <= 0) { + if(entering) { +#ifdef TEAMWARE_MAKE_CMN + sprintf( rcwd + , catgets(catd, 1, 329, "dmake: Entering directory `%s'\n") + , get_current_path()); +#else + sprintf( rcwd + , catgets(catd, 1, 330, "make: Entering directory `%s'\n") + , get_current_path()); +#endif + } else { +#ifdef TEAMWARE_MAKE_CMN + sprintf( rcwd + , catgets(catd, 1, 331, "dmake: Leaving directory `%s'\n") + , get_current_path()); +#else + sprintf( rcwd + , catgets(catd, 1, 332, "make: Leaving directory `%s'\n") + , get_current_path()); +#endif + } + } else { + if(entering) { +#ifdef TEAMWARE_MAKE_CMN + sprintf( rcwd + , catgets(catd, 1, 333, "dmake[%d]: Entering directory `%s'\n") + , make_level_val, get_current_path()); +#else + sprintf( rcwd + , catgets(catd, 1, 334, "make[%d]: Entering directory `%s'\n") + , make_level_val, get_current_path()); +#endif + } else { +#ifdef TEAMWARE_MAKE_CMN + sprintf( rcwd + , catgets(catd, 1, 335, "dmake[%d]: Leaving directory `%s'\n") + , make_level_val, get_current_path()); +#else + sprintf( rcwd + , catgets(catd, 1, 336, "make[%d]: Leaving directory `%s'\n") + , make_level_val, get_current_path()); +#endif + } + } + printf(NOCATGETS("%s"), rcwd); + } +} diff --git a/usr/src/make_src/Make/bin/make/common/make.cc b/usr/src/make_src/Make/bin/make/common/make.cc new file mode 100644 index 0000000..8096f2a --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/make.cc @@ -0,0 +1,29 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)make.cc 1.2 06/12/12 + */ + +#pragma ident "@(#)make.cc 1.2 06/12/12" diff --git a/usr/src/make_src/Make/bin/make/common/make.rules.file b/usr/src/make_src/Make/bin/make/common/make.rules.file new file mode 100644 index 0000000..3b4b7bf --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/make.rules.file @@ -0,0 +1,500 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)make.rules.file 1.22 06/12/12 +# + +SUFFIXES = .o .c .c~ .cc .cc~ .y .y~ .l .l~ .s .s~ .sh .sh~ .S .S~ .i .ln \ + .h .h~ .f .f~ .for .for~ .F .F~ .f90 .f90~ .ftn .ftn~ .mod .mod~ \ + .sym .def .def~ .p .p~ .r .r~ .cps .cps~ .C .C~ .Y .Y~ .L .L~ \ + .java .java~ .class + +.SUFFIXES: $(SUFFIXES) + +# OUTPUT_OPTION should be defined to "-o $@" when +# the default rules are used for non-local files. +OUTPUT_OPTION= + +# C language section. +CC=cc +CFLAGS= +CPPFLAGS= +LINT=lint +LINTFLAGS= +COMPILE.c=$(CC) $(CFLAGS) $(CPPFLAGS) -c +LINK.c=$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) +LINT.c=$(LINT) $(LINTFLAGS) $(CPPFLAGS) +.c: + $(LINK.c) -o $@ $< $(LDLIBS) +.c~: + $(GET) $(GFLAGS) -p $< > $*.c + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $*.c +.c.o: + $(COMPILE.c) $(OUTPUT_OPTION) $< +.c~.o: + $(GET) $(GFLAGS) -p $< > $*.c + $(CC) $(CFLAGS) -c $*.c +.c.i: + $(CC) $(CFLAGS) $(CPPFLAGS) -P $< +.c~.i: + $(GET) $(GFLAGS) -p $< > $*.c + $(CC) $(CFLAGS) $(CPPFLAGS) -P $*.c +.c.ln: + $(LINT.c) $(OUTPUT_OPTION) -c $< +.c~.ln: + $(GET) $(GFLAGS) -p $< > $*.c + $(LINT.c) $(OUTPUT_OPTION) -c $*.c +.c.a: + $(COMPILE.c) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.c~.a: + $(GET) $(GFLAGS) -p $< > $*.c + $(COMPILE.c) -o $% $*.c + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# C language section. yacc. +YACC=yacc +YFLAGS= +YACC.y=$(YACC) $(YFLAGS) +.y: + $(YACC.y) $< + $(LINK.c) -o $@ y.tab.c $(LDLIBS) + $(RM) y.tab.c +.y~: + $(GET) $(GFLAGS) -p $< > $*.y + $(YACC) $(YFLAGS) $*.y + $(COMPILE.c) -o $@ y.tab.c + $(RM) y.tab.c + +.y.c: + $(YACC.y) $< + mv y.tab.c $@ +.y~.c: + $(GET) $(GFLAGS) -p $< > $*.y + $(YACC) $(YFLAGS) $*.y + mv y.tab.c $@ +.y.ln: + $(YACC.y) $< + $(LINT.c) -o $@ -i y.tab.c + $(RM) y.tab.c +.y~.ln: + $(GET) $(GFLAGS) -p $< > $*.y + $(YACC.y) $*.y + $(LINT.c) -o $@ -i y.tab.c + $(RM) y.tab.c +.y.o: + $(YACC.y) $< + $(COMPILE.c) -o $@ y.tab.c + $(RM) y.tab.c +.y~.o: + $(GET) $(GFLAGS) -p $< > $*.y + $(YACC) $(YFLAGS) $*.y + $(CC) $(CFLAGS) -c y.tab.c + rm -f y.tab.c + mv y.tab.o $@ + +# C language section. lex. +LEX=lex +LFLAGS= +LEX.l=$(LEX) $(LFLAGS) -t +.l: + $(RM) $*.c + $(LEX.l) $< > $*.c + $(LINK.c) -o $@ $*.c -ll $(LDLIBS) + $(RM) $*.c +.l~: + $(GET) $(GFLAGS) -p $< > $*.l + $(LEX) $(LFLAGS) $*.l + $(CC) $(CFLAGS) -c lex.yy.c + rm -f lex.yy.c + mv lex.yy.c $@ + +.l.c : + $(RM) $@ + $(LEX.l) $< > $@ +.l~.c: + $(GET) $(GFLAGS) -p $< > $*.l + $(LEX) $(LFLAGS) $*.l + mv lex.yy.c $@ +.l.ln: + $(RM) $*.c + $(LEX.l) $< > $*.c + $(LINT.c) -o $@ -i $*.c + $(RM) $*.c +.l~.ln: + $(GET) $(GFLAGS) -p $< > $*.l + $(RM) $*.c + $(LEX.l) $*.l > $*.c + $(LINT.c) -o $@ -i $*.c + $(RM) $*.c +.l.o: + $(RM) $*.c + $(LEX.l) $< > $*.c + $(COMPILE.c) -o $@ $*.c + $(RM) $*.c +.l~.o: + $(GET) $(GFLAGS) -p $< > $*.l + $(LEX) $(LFLAGS) $*.l + $(CC) $(CFLAGS) -c lex.yy.c + rm -f lex.yy.c + mv lex.yy.c $@ + +# C++ language section. +CCC=CC +CCFLAGS= +COMPILE.cc=$(CCC) $(CCFLAGS) $(CPPFLAGS) -c +LINK.cc=$(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) +COMPILE.C=$(CCC) $(CCFLAGS) $(CPPFLAGS) -c +LINK.C=$(CCC) $(CCFLAGS) $(CPPFLAGS) $(LDFLAGS) +.cc: + $(LINK.cc) -o $@ $< $(LDLIBS) +.cc~: + $(GET) $(GFLAGS) -p $< > $*.cc + $(LINK.cc) -o $@ $*.cc $(LDLIBS) +.cc.o: + $(COMPILE.cc) $(OUTPUT_OPTION) $< +.cc~.o: + $(GET) $(GFLAGS) -p $< > $*.cc + $(COMPILE.cc) $(OUTPUT_OPTION) $*.cc +.cc.i: + $(CCC) $(CCFLAGS) $(CPPFLAGS) -P $< +.cc~.i: + $(GET) $(GFLAGS) -p $< > $*.cc + $(CCC) $(CCFLAGS) $(CPPFLAGS) -P $*.cc +.cc.a: + $(COMPILE.cc) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.cc~.a: + $(GET) $(GFLAGS) -p $< > $*.cc + $(COMPILE.cc) -o $% $*.cc + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +.C: + $(LINK.C) -o $@ $< $(LDLIBS) +.C~: + $(GET) $(GFLAGS) -p $< > $*.C + $(LINK.C) -o $@ $*.C $(LDLIBS) +.C.o: + $(COMPILE.C) $(OUTPUT_OPTION) $< +.C~.o: + $(GET) $(GFLAGS) -p $< > $*.C + $(COMPILE.C) $(OUTPUT_OPTION) $*.C +.C.i: + $(CCC) $(CCFLAGS) $(CPPFLAGS) -P $< +.C~.i: + $(GET) $(GFLAGS) -p $< > $*.C + $(CCC) $(CCFLAGS) $(CPPFLAGS) -P $*.C +.C.a: + $(COMPILE.C) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.C~.a: + $(GET) $(GFLAGS) -p $< > $*.C + $(COMPILE.C) -o $% $*.C + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# FORTRAN section. +FC=f77 +FFLAGS= +COMPILE.f=$(FC) $(FFLAGS) -c +LINK.f=$(FC) $(FFLAGS) $(LDFLAGS) +COMPILE.F=$(FC) $(FFLAGS) $(CPPFLAGS) -c +LINK.F=$(FC) $(FFLAGS) $(CPPFLAGS) $(LDFLAGS) +.f: + $(LINK.f) -o $@ $< $(LDLIBS) +.f~: + $(GET) $(GFLAGS) -p $< > $*.f + $(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.f +.f.o: + $(COMPILE.f) $(OUTPUT_OPTION) $< +.f~.o: + $(GET) $(GFLAGS) -p $< > $*.f + $(FC) $(FFLAGS) -c $*.f +.f.a: + $(COMPILE.f) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.f~.a: + $(GET) $(GFLAGS) -p $< > $*.f + $(COMPILE.f) -o $% $*.f + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.for: + $(LINK.f) -o $@ $< $(LDLIBS) +.for~: + $(GET) $(GFLAGS) -p $< > $*.for + $(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.for +.for.o: + $(COMPILE.f) $(OUTPUT_OPTION) $< +.for~.o: + $(GET) $(GFLAGS) -p $< > $*.for + $(FC) $(FFLAGS) -c $*.for +.for.a: + $(COMPILE.f) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.for~.a: + $(GET) $(GFLAGS) -p $< > $*.for + $(COMPILE.f) -o $% $*.for + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.F: + $(LINK.F) -o $@ $< $(LDLIBS) +.F~: + $(GET) $(GFLAGS) -p $< > $*.F + $(FC) $(FFLAGS) $(LDFLAGS) -o $@ $*.F +.F.o: + $(COMPILE.F) $(OUTPUT_OPTION) $< +.F~.o: + $(GET) $(GFLAGS) -p $< > $*.F + $(FC) $(FFLAGS) -c $*.F +.F.a: + $(COMPILE.F) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.F~.a: + $(GET) $(GFLAGS) -p $< > $*.F + $(COMPILE.F) -o $% $*.F + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# FORTRAN section. ratfor. +RFLAGS= +COMPILE.r=$(FC) $(FFLAGS) $(RFLAGS) -c +LINK.r=$(FC) $(FFLAGS) $(RFLAGS) $(LDFLAGS) +.r: + $(LINK.r) -o $@ $< $(LDLIBS) +.r~: + $(GET) $(GFLAGS) -p $< > $*.r + $(LINK.r) -o $@ $*.r $(LDLIBS) +.r.o: + $(COMPILE.r) $(OUTPUT_OPTION) $< +.r~.o: + $(GET) $(GFLAGS) -p $< > $*.r + $(COMPILE.r) $(OUTPUT_OPTION) $*.r +.r.a: + $(COMPILE.r) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.r~.a: + $(GET) $(GFLAGS) -p $< > $*.r + $(COMPILE.r) -o $% $*.r + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# FORTRAN 90 section. +F90C=f90 +F90FLAGS= +COMPILE.f90=$(F90C) $(F90FLAGS) -c +LINK.f90=$(F90C) $(F90FLAGS) $(LDFLAGS) +COMPILE.ftn=$(F90C) $(F90FLAGS) -c +LINK.ftn=$(F90C) $(F90FLAGS) $(LDFLAGS) +.f90: + $(LINK.f90) -o $@ $< $(LDLIBS) +.f90~: + $(GET) $(GFLAGS) -p $< > $*.f90 + $(LINK.f90) -o $@ $*.f90 $(LDLIBS) +.f90.o: + $(COMPILE.f90) $(OUTPUT_OPTION) $< +.f90~.o: + $(GET) $(GFLAGS) -p $< > $*.f90 + $(COMPILE.f90) $(OUTPUT_OPTION) $*.f90 +.f90.a: + $(COMPILE.f90) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.f90~.a: + $(GET) $(GFLAGS) -p $< > $*.f90 + $(COMPILE.f90) -o $% $*.f90 + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.ftn: + $(LINK.ftn) -o $@ $< $(LDLIBS) +.ftn~: + $(GET) $(GFLAGS) -p $< > $*.ftn + $(LINK.ftn) -o $@ $*.ftn $(LDLIBS) +.ftn.o: + $(COMPILE.ftn) $(OUTPUT_OPTION) $< +.ftn~.o: + $(GET) $(GFLAGS) -p $< > $*.ftn + $(COMPILE.ftn) $(OUTPUT_OPTION) $*.ftn +.ftn.a: + $(COMPILE.ftn) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.ftn~.a: + $(GET) $(GFLAGS) -p $< > $*.ftn + $(COMPILE.ftn) -o $% $*.ftn + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Modula-2 section. +M2C=m2c +M2FLAGS= +MODFLAGS= +DEFFLAGS= +COMPILE.def=$(M2C) $(M2FLAGS) $(DEFFLAGS) +COMPILE.mod=$(M2C) $(M2FLAGS) $(MODFLAGS) +.def.sym: + $(COMPILE.def) -o $@ $< +.def~.sym: + $(GET) $(GFLAGS) -p $< > $*.def + $(COMPILE.def) -o $@ $*.def +.mod: + $(COMPILE.mod) -o $@ -e $@ $< +.mod~: + $(GET) $(GFLAGS) -p $< > $*.mod + $(COMPILE.mod) -o $@ -e $@ $*.mod +.mod.o: + $(COMPILE.mod) -o $@ $< +.mod~.o: + $(GET) $(GFLAGS) -p $< > $*.mod + $(COMPILE.mod) -o $@ $*.mod +.mod.a: + $(COMPILE.mod) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.mod~.a: + $(GET) $(GFLAGS) -p $< > $*.mod + $(COMPILE.mod) -o $% $*.mod + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Pascal section. +PC=pc +PFLAGS= +COMPILE.p=$(PC) $(PFLAGS) $(CPPFLAGS) -c +LINK.p=$(PC) $(PFLAGS) $(CPPFLAGS) $(LDFLAGS) +.p: + $(LINK.p) -o $@ $< $(LDLIBS) +.p~: + $(GET) $(GFLAGS) -p $< > $*.p + $(LINK.p) -o $@ $*.p $(LDLIBS) +.p.o: + $(COMPILE.p) $(OUTPUT_OPTION) $< +.p~.o: + $(GET) $(GFLAGS) -p $< > $*.p + $(COMPILE.p) $(OUTPUT_OPTION) $*.p +.p.a: + $(COMPILE.p) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.p~.a: + $(GET) $(GFLAGS) -p $< > $*.p + $(COMPILE.p) -o $% $*.p + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Assembly section. +AS=as +ASFLAGS= +COMPILE.s=$(AS) $(ASFLAGS) +COMPILE.S=$(CC) $(ASFLAGS) $(CPPFLAGS) -c +.s.o: + $(COMPILE.s) -o $@ $< +.s~.o: + $(GET) $(GFLAGS) -p $< > $*.s + $(COMPILE.s) -o $@ $*.s +.s.a: + $(COMPILE.s) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.s~.a: + $(GET) $(GFLAGS) -p $< > $*.s + $(COMPILE.s) -o $% $*.s + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.S.o: + $(COMPILE.S) -o $@ $< +.S~.o: + $(GET) $(GFLAGS) -p $< > $*.S + $(COMPILE.S) -o $@ $*.S +.S.a: + $(COMPILE.S) -o $% $< + $(AR) $(ARFLAGS) $@ $% + $(RM) $% +.S~.a: + $(GET) $(GFLAGS) -p $< > $*.S + $(COMPILE.S) -o $% $*.S + $(AR) $(ARFLAGS) $@ $% + $(RM) $% + +# Shell section. +.sh: + $(RM) $@ + cat $< > $@ + chmod +x $@ +.sh~: + $(GET) $(GFLAGS) -p $< > $*.sh + cp $*.sh $@ + chmod a+x $@ + +# NeWS section +CPS=cps +CPSFLAGS= +.cps.h: + $(CPS) $(CPSFLAGS) $*.cps +.cps~.h: + $(GET) $(GFLAGS) -p $< > $*.cps + $(CPS) $(CPSFLAGS) $*.cps + +# JAVA section +JAVAC=javac +JAVACFLAGS= +.java.class: + $(JAVAC) $(JAVACFLAGS) $< +.java~.class: + $(GET) $(GFLAGS) -p $< > $*.java + $(JAVAC) $(JAVACFLAGS) $< + +# Miscellaneous section. +LD=ld +LDFLAGS= +LDLIBS= +MAKE=make +RM=rm -f +AR=ar +ARFLAGS=rv +GET=get +GFLAGS= + +markfile.o: markfile + echo "static char _sccsid[] = \"`grep @'(#)' markfile`\";" > markfile.c + cc -c markfile.c + $(RM) markfile.c + +SCCSFLAGS= +SCCSGETFLAGS=-s +.SCCS_GET: + sccs $(SCCSFLAGS) get $(SCCSGETFLAGS) $@ -G$@ + +.SCCS_GET_POSIX: + sccs $(SCCSFLAGS) get $(SCCSGETFLAGS) $@ + +.GET_POSIX: + $(GET) $(GFLAGS) s.$@ diff --git a/usr/src/make_src/Make/bin/make/common/misc.cc b/usr/src/make_src/Make/bin/make/common/misc.cc new file mode 100644 index 0000000..d718de0 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/misc.cc @@ -0,0 +1,1007 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)misc.cc 1.50 06/12/12 + */ + +#pragma ident "@(#)misc.cc 1.34 95/10/04" + +/* + * misc.cc + * + * This file contains various unclassified routines. Some main groups: + * getname + * Memory allocation + * String handling + * Property handling + * Error message handling + * Make internal state dumping + * main routine support + */ + +/* + * Included files + */ +#include <errno.h> +#include <mk/defs.h> +#include <mksh/macro.h> /* SETVAR() */ +#include <mksh/misc.h> /* enable_interrupt() */ +#include <stdarg.h> /* va_list, va_start(), va_end() */ +#include <vroot/report.h> /* SUNPRO_DEPENDENCIES */ + +#if defined(HP_UX) || defined(linux) +#include <unistd.h> +#endif + +#ifdef TEAMWARE_MAKE_CMN +#define MAXJOBS_ADJUST_RFE4694000 + +#ifdef MAXJOBS_ADJUST_RFE4694000 +extern void job_adjust_fini(); +#endif /* MAXJOBS_ADJUST_RFE4694000 */ +#endif /* TEAMWARE_MAKE_CMN */ + +#if defined(linux) +#include <time.h> /* localtime() */ +#endif + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +/* + * File table of contents + */ +static void print_rule(register Name target); +static void print_target_n_deps(register Name target); + +/***************************************** + * + * getname + */ + +/***************************************** + * + * Memory allocation + */ + +/* + * free_chain() + * + * frees a chain of Name_vector's + * + * Parameters: + * ptr Pointer to the first element in the chain + * to be freed. + * + * Global variables used: + */ +void +free_chain(Name_vector ptr) +{ + if (ptr != NULL) { + if (ptr->next != NULL) { + free_chain(ptr->next); + } + free((char *) ptr); + } +} + +/***************************************** + * + * String manipulation + */ + +/***************************************** + * + * Nameblock property handling + */ + +/***************************************** + * + * Error message handling + */ + +/* + * fatal(format, args...) + * + * Print a message and die + * + * Parameters: + * format printf type format string + * args Arguments to match the format + * + * Global variables used: + * fatal_in_progress Indicates if this is a recursive call + * parallel_process_cnt Do we need to wait for anything? + * report_pwd Should we report the current path? + */ +/*VARARGS*/ +void +fatal(char * message, ...) +{ + va_list args; + + va_start(args, message); + (void) fflush(stdout); +#ifdef DISTRIBUTED + (void) fprintf(stderr, catgets(catd, 1, 262, "dmake: Fatal error: ")); +#else + (void) fprintf(stderr, catgets(catd, 1, 263, "make: Fatal error: ")); +#endif + (void) vfprintf(stderr, message, args); + (void) fprintf(stderr, "\n"); + va_end(args); + if (report_pwd) { + (void) fprintf(stderr, + catgets(catd, 1, 156, "Current working directory %s\n"), + get_current_path()); + } + (void) fflush(stderr); + if (fatal_in_progress) { +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + exit_status = 1; +#endif + exit(1); + } + fatal_in_progress = true; +#ifdef TEAMWARE_MAKE_CMN + /* Let all parallel children finish */ + if ((dmake_mode_type == parallel_mode) && + (parallel_process_cnt > 0)) { + (void) fprintf(stderr, + catgets(catd, 1, 157, "Waiting for %d %s to finish\n"), + parallel_process_cnt, + parallel_process_cnt == 1 ? + catgets(catd, 1, 158, "job") : catgets(catd, 1, 159, "jobs")); + (void) fflush(stderr); + } + + while (parallel_process_cnt > 0) { +#ifdef DISTRIBUTED + if (dmake_mode_type == distributed_mode) { + (void) await_dist(false); + } else { + await_parallel(true); + } +#else + await_parallel(true); +#endif + finish_children(false); + } +#endif + +#if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000) + job_adjust_fini(); +#endif + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + exit_status = 1; +#endif + exit(1); +} + +/* + * warning(format, args...) + * + * Print a message and continue. + * + * Parameters: + * format printf type format string + * args Arguments to match the format + * + * Global variables used: + * report_pwd Should we report the current path? + */ +/*VARARGS*/ +void +warning(char * message, ...) +{ + va_list args; + + va_start(args, message); + (void) fflush(stdout); +#ifdef DISTRIBUTED + (void) fprintf(stderr, catgets(catd, 1, 264, "dmake: Warning: ")); +#else + (void) fprintf(stderr, catgets(catd, 1, 265, "make: Warning: ")); +#endif + (void) vfprintf(stderr, message, args); + (void) fprintf(stderr, "\n"); + va_end(args); + if (report_pwd) { + (void) fprintf(stderr, + catgets(catd, 1, 161, "Current working directory %s\n"), + get_current_path()); + } + (void) fflush(stderr); +} + +/* + * time_to_string(time) + * + * Take a numeric time value and produce + * a proper string representation. + * + * Return value: + * The string representation of the time + * + * Parameters: + * time The time we need to translate + * + * Global variables used: + */ +char * +time_to_string(const timestruc_t &time) +{ + struct tm *tm; + char buf[128]; + + if (time == file_doesnt_exist) { + return catgets(catd, 1, 163, "File does not exist"); + } + if (time == file_max_time) { + return catgets(catd, 1, 164, "Younger than any file"); + } + tm = localtime(&time.tv_sec); + strftime(buf, sizeof (buf), NOCATGETS("%c %Z"), tm); + buf[127] = (int) nul_char; + return strdup(buf); +} + +/* + * get_current_path() + * + * Stuff current_path with the current path if it isnt there already. + * + * Parameters: + * + * Global variables used: + */ +char * +get_current_path(void) +{ + char pwd[(MAXPATHLEN * MB_LEN_MAX)]; + static char *current_path; + + if (current_path == NULL) { +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + getcwd(pwd, sizeof(pwd)); +#else + (void) getwd(pwd); +#endif + if (pwd[0] == (int) nul_char) { + pwd[0] = (int) slash_char; + pwd[1] = (int) nul_char; +#ifdef DISTRIBUTED + current_path = strdup(pwd); + } else if (IS_EQUALN(pwd, NOCATGETS("/tmp_mnt"), 8)) { + current_path = strdup(pwd + 8); + } else { + current_path = strdup(pwd); + } +#else + } + current_path = strdup(pwd); +#endif + } + return current_path; +} + +/***************************************** + * + * Make internal state dumping + * + * This is a set of routines for dumping the internal make state + * Used for the -p option + */ + +/* + * dump_make_state() + * + * Dump make's internal state to stdout + * + * Parameters: + * + * Global variables used: + * svr4 Was ".SVR4" seen in makefile? + * svr4_name The Name ".SVR4", printed + * posix Was ".POSIX" seen in makefile? + * posix_name The Name ".POSIX", printed + * default_rule Points to the .DEFAULT rule + * default_rule_name The Name ".DEFAULT", printed + * default_target_to_build The first target to print + * dot_keep_state The Name ".KEEP_STATE", printed + * dot_keep_state_file The Name ".KEEP_STATE_FILE", printed + * hashtab The make hash table for Name blocks + * ignore_errors Was ".IGNORE" seen in makefile? + * ignore_name The Name ".IGNORE", printed + * keep_state Was ".KEEP_STATE" seen in makefile? + * percent_list The list of % rules + * precious The Name ".PRECIOUS", printed + * sccs_get_name The Name ".SCCS_GET", printed + * sccs_get_posix_name The Name ".SCCS_GET_POSIX", printed + * get_name The Name ".GET", printed + * get_posix_name The Name ".GET_POSIX", printed + * sccs_get_rule Points to the ".SCCS_GET" rule + * silent Was ".SILENT" seen in makefile? + * silent_name The Name ".SILENT", printed + * suffixes The suffix list from ".SUFFIXES" + * suffixes_name The Name ".SUFFIX", printed + */ +void +dump_make_state(void) +{ + Name_set::iterator p, e; + register Property prop; + register Dependency dep; + register Cmd_line rule; + Percent percent, percent_depe; + + /* Default target */ + if (default_target_to_build != NULL) { + print_rule(default_target_to_build); + } + (void) printf("\n"); + + /* .POSIX */ + if (posix) { + (void) printf("%s:\n", posix_name->string_mb); + } + + /* .DEFAULT */ + if (default_rule != NULL) { + (void) printf("%s:\n", default_rule_name->string_mb); + for (rule = default_rule; rule != NULL; rule = rule->next) { + (void) printf("\t%s\n", rule->command_line->string_mb); + } + } + + /* .IGNORE */ + if (ignore_errors) { + (void) printf("%s:\n", ignore_name->string_mb); + } + + /* .KEEP_STATE: */ + if (keep_state) { + (void) printf("%s:\n\n", dot_keep_state->string_mb); + } + + /* .PRECIOUS */ + (void) printf("%s:", precious->string_mb); + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { + if ((p->stat.is_precious) || (all_precious)) { + (void) printf(" %s", p->string_mb); + } + } + (void) printf("\n"); + + /* .SCCS_GET */ + if (sccs_get_rule != NULL) { + (void) printf("%s:\n", sccs_get_name->string_mb); + for (rule = sccs_get_rule; rule != NULL; rule = rule->next) { + (void) printf("\t%s\n", rule->command_line->string_mb); + } + } + + /* .SILENT */ + if (silent) { + (void) printf("%s:\n", silent_name->string_mb); + } + + /* .SUFFIXES: */ + (void) printf("%s:", suffixes_name->string_mb); + for (dep = suffixes; dep != NULL; dep = dep->next) { + (void) printf(" %s", dep->name->string_mb); + build_suffix_list(dep->name); + } + (void) printf("\n\n"); + + /* % rules */ + for (percent = percent_list; + percent != NULL; + percent = percent->next) { + (void) printf("%s:", + percent->name->string_mb); + + for (percent_depe = percent->dependencies; + percent_depe != NULL; + percent_depe = percent_depe->next) { + (void) printf(" %s", percent_depe->name->string_mb); + } + + (void) printf("\n"); + + for (rule = percent->command_template; + rule != NULL; + rule = rule->next) { + (void) printf("\t%s\n", rule->command_line->string_mb); + } + } + + /* Suffix rules */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { + Wstring wcb(p); + if (wcb.get_string()[0] == (int) period_char) { + print_rule(p); + } + } + + /* Macro assignments */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { + if (((prop = get_prop(p->prop, macro_prop)) != NULL) && + (prop->body.macro.value != NULL)) { + (void) printf("%s", p->string_mb); + print_value(prop->body.macro.value, + (Daemon) prop->body.macro.daemon); + } + } + (void) printf("\n"); + + /* Conditional macro assignments */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { + for (prop = get_prop(p->prop, conditional_prop); + prop != NULL; + prop = get_prop(prop->next, conditional_prop)) { + (void) printf("%s := %s", + p->string_mb, + prop->body.conditional.name-> + string_mb); + if (prop->body.conditional.append) { + printf(" +"); + } + else { + printf(" "); + } + print_value(prop->body.conditional.value, + no_daemon); + } + } + (void) printf("\n"); + + /* All other dependencies */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { + if (p->colons != no_colon) { + print_rule(p); + } + } + (void) printf("\n"); +} + +/* + * print_rule(target) + * + * Print the rule for one target + * + * Parameters: + * target Target we print rule for + * + * Global variables used: + */ +static void +print_rule(register Name target) +{ + register Cmd_line rule; + register Property line; + register Dependency dependency; + + if (target->dependency_printed || + ((line = get_prop(target->prop, line_prop)) == NULL) || + ((line->body.line.command_template == NULL) && + (line->body.line.dependencies == NULL))) { + return; + } + target->dependency_printed = true; + + (void) printf("%s:", target->string_mb); + + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + (void) printf(" %s", dependency->name->string_mb); + } + + (void) printf("\n"); + + for (rule = line->body.line.command_template; + rule != NULL; + rule = rule->next) { + (void) printf("\t%s\n", rule->command_line->string_mb); + } +} + +void +dump_target_list(void) +{ + Name_set::iterator p, e; + Wstring str; + + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) { + str.init(p); + wchar_t * wcb = str.get_string(); + if ((p->colons != no_colon) && + ((wcb[0] != (int) period_char) || + ((wcb[0] == (int) period_char) && + (wschr(wcb, (int) slash_char))))) { + print_target_n_deps(p); + } + } +} + +static void +print_target_n_deps(register Name target) +{ + register Cmd_line rule; + register Property line; + register Dependency dependency; + + if (target->dependency_printed) { + return; + } + target->dependency_printed = true; + + (void) printf("%s\n", target->string_mb); + + if ((line = get_prop(target->prop, line_prop)) == NULL) { + return; + } + for (dependency = line->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + if (!dependency->automatic) { + print_target_n_deps(dependency->name); + } + } +} + +/***************************************** + * + * main() support + */ + +/* + * load_cached_names() + * + * Load the vector of cached names + * + * Parameters: + * + * Global variables used: + * Many many pointers to Name blocks. + */ +void +load_cached_names(void) +{ + char *cp; + Name dollar; + + /* Load the cached_names struct */ + MBSTOWCS(wcs_buffer, NOCATGETS(".BUILT_LAST_MAKE_RUN")); + built_last_make_run = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("@")); + c_at = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(" *conditionals* ")); + conditionals = GETNAME(wcs_buffer, FIND_LENGTH); + /* + * A version of make was released with NSE 1.0 that used + * VERSION-1.1 but this version is identical to VERSION-1.0. + * The version mismatch code makes a special case for this + * situation. If the version number is changed from 1.0 + * it should go to 1.2. + */ + MBSTOWCS(wcs_buffer, NOCATGETS("VERSION-1.0")); + current_make_version = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".SVR4")); + svr4_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".POSIX")); + posix_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".DEFAULT")); + default_rule_name = GETNAME(wcs_buffer, FIND_LENGTH); +#ifdef NSE + MBSTOWCS(wcs_buffer, NOCATGETS(".DERIVED_SRC")); + derived_src= GETNAME(wcs_buffer, FIND_LENGTH); +#endif + MBSTOWCS(wcs_buffer, NOCATGETS("$")); + dollar = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".DONE")); + done = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".")); + dot = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".KEEP_STATE")); + dot_keep_state = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".KEEP_STATE_FILE")); + dot_keep_state_file = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("")); + empty_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(" FORCE")); + force = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("HOST_ARCH")); + host_arch = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("HOST_MACH")); + host_mach = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".IGNORE")); + ignore_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".INIT")); + init = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".LOCAL")); + localhost_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".make.state")); + make_state = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("MAKEFLAGS")); + makeflags = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".MAKE_VERSION")); + make_version = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".NO_PARALLEL")); + no_parallel_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".NOT_AUTO")); + not_auto = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".PARALLEL")); + parallel_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("PATH")); + path_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("+")); + plus = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".PRECIOUS")); + precious = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("?")); + query = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("^")); + hat = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".RECURSIVE")); + recursive_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".SCCS_GET")); + sccs_get_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".SCCS_GET_POSIX")); + sccs_get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".GET")); + get_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".GET_POSIX")); + get_posix_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("SHELL")); + shell_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".SILENT")); + silent_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".SUFFIXES")); + suffixes_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, SUNPRO_DEPENDENCIES); + sunpro_dependencies = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("TARGET_ARCH")); + target_arch = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("TARGET_MACH")); + target_mach = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("VIRTUAL_ROOT")); + virtual_root = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("VPATH")); + vpath_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS(".WAIT")); + wait_name = GETNAME(wcs_buffer, FIND_LENGTH); + + wait_name->state = build_ok; + + /* Mark special targets so that the reader treats them properly */ + svr4_name->special_reader = svr4_special; + posix_name->special_reader = posix_special; + built_last_make_run->special_reader = built_last_make_run_special; + default_rule_name->special_reader = default_special; +#ifdef NSE + derived_src->special_reader= derived_src_special; +#endif + dot_keep_state->special_reader = keep_state_special; + dot_keep_state_file->special_reader = keep_state_file_special; + ignore_name->special_reader = ignore_special; + make_version->special_reader = make_version_special; + no_parallel_name->special_reader = no_parallel_special; + parallel_name->special_reader = parallel_special; + localhost_name->special_reader = localhost_special; + precious->special_reader = precious_special; + sccs_get_name->special_reader = sccs_get_special; + sccs_get_posix_name->special_reader = sccs_get_posix_special; + get_name->special_reader = get_special; + get_posix_name->special_reader = get_posix_special; + silent_name->special_reader = silent_special; + suffixes_name->special_reader = suffixes_special; + + /* The value of $$ is $ */ + (void) SETVAR(dollar, dollar, false); + dollar->dollar = false; + + /* Set the value of $(SHELL) */ + #ifdef HP_UX + MBSTOWCS(wcs_buffer, NOCATGETS("/bin/posix/sh")); + #else + #if defined(SUN5_0) + if (posix) { + MBSTOWCS(wcs_buffer, NOCATGETS("/usr/xpg4/bin/sh")); + } else { + MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh")); + } + #else /* ^SUN5_0 */ + MBSTOWCS(wcs_buffer, NOCATGETS("/bin/sh")); + #endif /* ^SUN5_0 */ + #endif + (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false); + + /* + * Use " FORCE" to simulate a FRC dependency for :: type + * targets with no dependencies. + */ + (void) append_prop(force, line_prop); + force->stat.time = file_max_time; + + /* Make sure VPATH is defined before current dir is read */ + if ((cp = getenv(vpath_name->string_mb)) != NULL) { + MBSTOWCS(wcs_buffer, cp); + (void) SETVAR(vpath_name, + GETNAME(wcs_buffer, FIND_LENGTH), + false); + } + + /* Check if there is NO PATH variable. If not we construct one. */ + if (getenv(path_name->string_mb) == NULL) { + vroot_path = NULL; + add_dir_to_path(NOCATGETS("."), &vroot_path, -1); + add_dir_to_path(NOCATGETS("/bin"), &vroot_path, -1); + add_dir_to_path(NOCATGETS("/usr/bin"), &vroot_path, -1); + } +} + +/* + * iterate on list of conditional macros in np, and place them in + * a String_rec starting with, and separated by the '$' character. + */ +void +cond_macros_into_string(Name np, String_rec *buffer) +{ + Macro_list macro_list; + + /* + * Put the version number at the start of the string + */ + MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); + append_string(wcs_buffer, buffer, FIND_LENGTH); + /* + * Add the rest of the conditional macros to the buffer + */ + if (np->depends_on_conditional){ + for (macro_list = np->conditional_macro_list; + macro_list != NULL; macro_list = macro_list->next){ + append_string(macro_list->macro_name, buffer, + FIND_LENGTH); + append_char((int) equal_char, buffer); + append_string(macro_list->value, buffer, FIND_LENGTH); + append_char((int) dollar_char, buffer); + } + } +} +/* + * Copyright (c) 1987-1992 Sun Microsystems, Inc. All Rights Reserved. + * Sun considers its source code as an unpublished, proprietary + * trade secret, and it is available only under strict license + * provisions. This copyright notice is placed here only to protect + * Sun in the event the source is deemed a published work. Dissassembly, + * decompilation, or other means of reducing the object code to human + * readable form is prohibited by the license agreement under which + * this code is provided to the user or company in possession of this + * copy. + * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by the + * Government is subject to restrictions as set forth in subparagraph + * (c)(1)(ii) of the Rights in Technical Data and Computer Software + * clause at DFARS 52.227-7013 and in similar clauses in the FAR and + * NASA FAR Supplement. + * + * 1.3 91/09/30 + */ + + +/* Some includes are commented because of the includes at the beginning */ +/* #include <signal.h> */ +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +/* #include <string.h> */ +#include <unistd.h> +#include <stdlib.h> +/* #include <stdio.h> */ +/* #include <avo/find_dir.h> */ +/* #ifndef TEAMWARE_MAKE_CMN +#include <avo/find_dir.h> +#endif */ + +/* Routines to find the base directory name from which the various components + * -executables, *crt* libraries etc will be accessed + */ + +/* This routine checks to see if a given filename is an executable or not. + Logically similar to the csh statement : if ( -x $i && ! -d $i ) + */ + +static int +check_if_exec(char *file) +{ + struct stat stb; + if (stat(file, &stb) < 0) { + return ( -1); + } + if (S_ISDIR(stb.st_mode)) { + return (-1); + } + if (!(stb.st_mode & S_IEXEC)) { + return ( -1); + } + return (0); +} + +/* resolve - check for specified file in specified directory + * sets up dir, following symlinks. + * returns zero for success, or + * -1 for error (with errno set properly) + */ +static int +resolve (char *indir, /* search directory */ + char *cmd, /* search for name */ + char *dir, /* directory buffer */ + char **run) /* resultion name ptr ptr */ +{ + char *p; + int rv = -1; + int sll; + char symlink[MAXPATHLEN + 1]; + + do { + errno = ENAMETOOLONG; + if ((strlen (indir) + strlen (cmd) + 2) > (size_t) MAXPATHLEN) + break; + + sprintf(dir, "%s/%s", indir, cmd); + if (check_if_exec(dir) != 0) /* check if dir is an executable */ + { + break; /* Not an executable program */ + } + + /* follow symbolic links */ + while ((sll = readlink (dir, symlink, MAXPATHLEN)) >= 0) { + symlink[sll] = 0; + if (*symlink == '/') + strcpy (dir, symlink); + else + sprintf (strrchr (dir, '/'), "/%s", symlink); + } + if (errno != EINVAL) + break; + + p = strrchr (dir, '/'); + *p++ = 0; + if (run) /* user wants resolution name */ + *run = p; + rv = 0; /* complete, with success! */ + + } while (0); + + return rv; +} + +/* + *find_run_directory - find executable file in PATH + * + * PARAMETERS: + * cmd filename as typed by user (argv[0]) + * cwd buffer from which is read the working directory + * if first character is '/' or into which is + * copied working directory name otherwise + * dir buffer into which is copied program's directory + * pgm where to return pointer to tail of cmd (may be NULL + * if not wanted) + * run where to return pointer to tail of final resolved + * name ( dir/run is the program) (may be NULL + * if not wanted) + * path user's path from environment + * + * Note: run and pgm will agree except when symbolic links have + * renamed files + * + * RETURNS: + * returns zero for success, + * -1 for error (with errno set properly). + * + * EXAMPLE: + * find_run_directory (argv[0], ".", &charray1, (char **) 0, (char **) 0, + * getenv(NOGETTEXT("PATH"))); + */ +extern int +find_run_directory (char *cmd, + char *cwd, + char *dir, + char **pgm, + char **run, + char *path) +{ + int rv = 0; + char *f, *s; + int i; + char tmp_path[MAXPATHLEN]; + + if (!cmd || !*cmd || !cwd || !dir) { + errno = EINVAL; /* stupid arguments! */ + return -1; + } + + if (*cwd != '/') + if (!(getcwd (cwd, MAXPATHLEN))) + return -1; /* can not get working directory */ + + f = strrchr (cmd, '/'); + if (pgm) /* user wants program name */ + *pgm = f ? f + 1 : cmd; + + /* get program directory */ + rv = -1; + if (*cmd == '/') /* absname given */ + rv = resolve ("", cmd + 1, dir, run); + else if (f) /* relname given */ + rv = resolve (cwd, cmd, dir, run); + else { /* from searchpath */ + if (!path || !*path) { /* if missing or null path */ + tmp_path[0] = '.'; /* assume sanity */ + tmp_path[1] = '\0'; + } else { + strcpy(tmp_path, path); + } + f = tmp_path; + rv = -1; + errno = ENOENT; /* errno gets this if path empty */ + while (*f && (rv < 0)) { + s = f; + while (*f && (*f != ':')) + ++f; + if (*f) + *f++ = 0; + if (*s == '/') + rv = resolve (s, cmd, dir, run); + else { + char abuf[MAXPATHLEN]; + + sprintf (abuf, "%s/%s", cwd, s); + rv = resolve (abuf, cmd, dir, run); + } + } + } + + /* Remove any trailing /. */ + i = strlen(dir); + if ( dir[i-2] == '/' && dir[i-1] == '.') { + dir[i-2] = '\0'; + } + + return rv; +} + diff --git a/usr/src/make_src/Make/bin/make/common/nse.cc b/usr/src/make_src/Make/bin/make/common/nse.cc new file mode 100644 index 0000000..4cc75e4 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/nse.cc @@ -0,0 +1,610 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)nse.cc 1.15 06/12/12 + */ + +#pragma ident "@(#)nse.cc 1.15 06/12/12" + +#ifdef NSE + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/macro.h> /* expand_value() */ +#include <mksh/misc.h> /* get_prop() */ + +/* + * This file does some extra checking on behalf of the NSE. + * It does some stuff that is analogous to lint in that it + * looks for things which may be legal but that give the NSE + * trouble. Currently it looks for: + * 1) recursion by cd'ing to a directory specified by a + * make variable that is defined from the shell environment. + * 2) recursion by cd'ing to a directory specified by a + * make variable that has backquotes in it. + * 3) recursion to another makefile in the same directory. + * 4) a dependency upon an SCCS file (SCCS/s.*) + * 5) backquotes in a file name + * 6) a make variable being defined on the command-line that + * ends up affecting dependencies + * 7) wildcards (*[) in dependencies + * 8) recursion to the same directory + * 9) potential source files on the left-hand-side so + * that they appear as derived files + * + * Things it should look for: + * 1) makefiles that are symlinks (why are these a problem?) + */ + +#define TARG_SUFX "/usr/nse/lib/nse_targ.sufx" + +typedef struct _Nse_suffix *Nse_suffix, Nse_suffix_rec; +struct _Nse_suffix { + wchar_t *suffix; /* The suffix */ + struct _Nse_suffix *next; /* Linked list */ +}; +static Nse_suffix sufx_hdr; +static int our_exit_status; + +static void nse_warning(void); +static Boolean nse_gettoken(wchar_t **, wchar_t *); + +/* + * Given a command that has just recursed to a sub make + * try to determine if it cd'ed to a directory that was + * defined by a make variable imported from the shell + * environment or a variable with backquotes in it. + * This routine will find something like: + * cd $(DIR); $(MAKE) + * where DIR is imported from the shell environment. + * However it well not find: + * CD = cd + * $(CD) $(DIR); $(MAKE) + * or + * CD = cd $(DIR) + * $(CD); $(MAKE) + * + * This routine also checks for recursion to the same + * directory. + */ +void +nse_check_cd(Property prop) +{ + wchar_t tok[512]; + wchar_t *p; + wchar_t *our_template; + int len; + Boolean cd; +#ifdef SUNOS4_AND_AFTER + String_rec string; +#else + String string; +#endif + Name name; + Name target; + struct Line *line; + struct Recursive *r; + Property recurse; + wchar_t strbuf[STRING_BUFFER_LENGTH]; + wchar_t tmpbuf[STRING_BUFFER_LENGTH]; + +#ifdef LTEST + printf("In nse_check_cd, nse = %d, nse_did_recursion = %d\n", nse, nse_did_recursion); +#endif +#ifdef SUNOS4_AND_AFTER + if (!nse_did_recursion || !nse) { +#else + if (is_false(nse_did_recursion) || is_false(flag.nse)) { +#endif +#ifdef LTEST + printf ("returning, nse = %d, nse_did_recursion = %d\n", nse, nse_did_recursion); +#endif + return; + } + line = &prop->body.line; +#ifdef LTEST + printf("string = %s\n", line->command_template->command_line->string_mb); +#endif + + wscpy(tmpbuf, line->command_template->command_line->string); + our_template = tmpbuf; + cd = false; + while (nse_gettoken(&our_template, tok)) { +#ifdef LTEST + printf("in gettoken loop\n"); +#endif +#ifdef SUNOS4_AND_AFTER + if (IS_WEQUAL(tok, (wchar_t *) "cd")) { +#else + if (is_equal(tok, "cd")) { +#endif + cd = true; + } else if (cd && tok[0] == '$') { + nse_backquote_seen = NULL; + nse_shell_var_used = NULL; + nse_watch_vars = true; +#ifdef SUNOS4_AND_AFTER + INIT_STRING_FROM_STACK(string, strbuf); + name = GETNAME(tok, FIND_LENGTH); +#else + init_string_from_stack(string, strbuf); + name = getname(tok, FIND_LENGTH); +#endif + expand_value(name, &string, false); + nse_watch_vars = false; + +#ifdef LTEST + printf("cd = %d, tok = $\n", cd); +#endif + /* + * Try to trim tok to just + * the variable. + */ + if (nse_shell_var_used != NULL) { + nse_warning(); + fprintf(stderr, "\tMake invoked recursively by cd'ing to a directory\n\tdefined by the shell environment variable %s\n\tCommand line: %s\n", + nse_shell_var_used->string_mb, + line->command_template->command_line->string_mb); + } + if (nse_backquote_seen != NULL) { + nse_warning(); + fprintf(stderr, "\tMake invoked recursively by cd'ing to a directory\n\tdefined by a variable (%s) with backquotes in it\n\tCommand line: %s\n", + nse_backquote_seen->string_mb, + line->command_template->command_line->string_mb); + } + cd = false; + } else if (cd && nse_backquotes(tok)) { + nse_warning(); + fprintf(stderr, "\tMake invoked recursively by cd'ing to a directory\n\tspecified by a command in backquotes\n\tCommand line: %s\n", + line->command_template->command_line->string_mb); + cd = false; + } else { + cd = false; + } + } + + /* + * Now check for recursion to ".". + */ + if (primary_makefile != NULL) { + target = prop->body.line.target; + recurse = get_prop(target->prop, recursive_prop); + while (recurse != NULL) { + r = &recurse->body.recursive; +#ifdef SUNOS4_AND_AFTER + if (IS_WEQUAL(r->directory->string, (wchar_t *) ".") && + !IS_WEQUAL(r->makefiles->name->string, + primary_makefile->string)) { +#else + if (is_equal(r->directory->string, ".") && + !is_equal(r->makefiles->name->string, + primary_makefile->string)) { +#endif + nse_warning(); + fprintf(stderr, "\tRecursion to makefile `%s' in the same directory\n\tCommand line: %s\n", + r->makefiles->name->string_mb, + line->command_template->command_line->string_mb); + } + recurse = get_prop(recurse->next, recursive_prop); + } + } +} + +/* + * Print an NSE make warning line. + * If the -P flag was given then consider this a fatal + * error, otherwise, just a warning. + */ +static void +nse_warning(void) +{ +#ifdef SUNOS4_AND_AFTER + if (report_dependencies_level > 0) { +#else + if (is_true(flag.report_dependencies)) { +#endif + our_exit_status = 1; + } + if (primary_makefile != NULL) { + fprintf(stderr, "make: NSE warning from makefile %s/%s:\n", + get_current_path(), primary_makefile->string_mb); + } else { + fprintf(stderr, "make: NSE warning from directory %s:\n", + get_current_path()); + } +} + +/* + * Get the next whitespace delimited token pointed to by *cp. + * Return it in tok. + */ +static Boolean +nse_gettoken(wchar_t **cp, wchar_t *tok) +{ + wchar_t *to; + wchar_t *p; + + p = *cp; + while (*p && iswspace(*p)) { + p++; + } + if (*p == '\0') { + return false; + } + to = tok; + while (*p && !iswspace(*p)) { + *to++ = *p++; + } + if (*p == '\0') { + return false; + } + *to = '\0'; + *cp = p; + return true; +} + +/* + * Given a dependency and a target, see if the dependency + * is an SCCS file. Check for the last component of its name + * beginning with "s." and the component before that being "SCCS". + * The NSE does not consider a source file to be derived from + * an SCCS file. + */ +void +nse_check_sccs(wchar_t *targ, wchar_t *dep) +{ + wchar_t *slash; + wchar_t *p; + +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } +#ifdef SUNOS4_AND_AFTER + slash = wsrchr(dep, (int) slash_char); +#else + slash = rindex(dep, '/'); +#endif + if (slash == NULL) { + return; + } + if (slash[1] != 's' || slash[2] != '.') { + return; + } + + /* + * Find the next to last filename component. + */ + for (p = slash - 1; p >= dep; p--) { + if (*p == '/') { + break; + } + } + p++; +#ifdef SUNOS4_AND_AFTER + MBSTOWCS(wcs_buffer, "SCCS/"); + if (IS_WEQUALN(p, wcs_buffer, wslen(wcs_buffer))) { +#else + if (is_equaln(p, "SCCS/", 5)) { +#endif + nse_warning(); + WCSTOMBS(mbs_buffer, targ); + WCSTOMBS(mbs_buffer2, dep); + fprintf(stderr, "\tFile `%s' depends upon SCCS file `%s'\n", + mbs_buffer, mbs_buffer2); + } + return; +} + +/* + * Given a filename check to see if it has 2 backquotes in it. + * Complain about this because the shell expands the backquotes + * but make does not so the files always appear to be out of date. + */ +void +nse_check_file_backquotes(wchar_t *file) +{ +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } + if (nse_backquotes(file)) { + nse_warning(); + WCSTOMBS(mbs_buffer, file); + fprintf(stderr, "\tFilename \"%s\" has backquotes in it\n", + mbs_buffer); + } +} + +/* + * Return true if the string has two backquotes in it. + */ +Boolean +nse_backquotes(wchar_t *str) +{ + wchar_t *bq; + +#ifdef SUNOS4_AND_AFTER + bq = wschr(str, (int) backquote_char); + if (bq) { + bq = wschr(&bq[1], (int) backquote_char); +#else + bq = index(str, '`'); + if (bq) { + bq = index(&bq[1], '`'); +#endif + if (bq) { + return true; + } + } + return false; +} + +/* + * A macro that was defined on the command-line was found to affect the + * set of dependencies. The NSE "target explode" will not know about + * this and will not get the same set of dependencies. + */ +void +nse_dep_cmdmacro(wchar_t *macro) +{ +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } + nse_warning(); + WCSTOMBS(mbs_buffer, macro); + fprintf(stderr, "\tVariable `%s' is defined on the command-line and\n\taffects dependencies\n", + mbs_buffer); +} + +/* + * A macro that was defined on the command-line was found to + * be part of the argument to a cd before a recursive make. + * This make cause the make to recurse to different places + * depending upon how it is invoked. + */ +void +nse_rule_cmdmacro(wchar_t *macro) +{ +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } + nse_warning(); + WCSTOMBS(mbs_buffer, macro); + fprintf(stderr, "\tMake invoked recursively by cd'ing to a directory\n\tspecified by a variable (%s) defined on the command-line\n", + mbs_buffer); +} + +/* + * A dependency has been found with a wildcard in it. + * This causes the NSE problems because the set of dependencies + * can change without changing the Makefile. + */ +void +nse_wildcard(wchar_t *targ, wchar_t *dep) +{ +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } + nse_warning(); + WCSTOMBS(mbs_buffer, targ); + WCSTOMBS(mbs_buffer2, dep); + fprintf(stderr, "\tFile `%s' has a wildcard in dependency `%s'\n", + mbs_buffer, mbs_buffer2); +} + +/* + * Read in the list of suffixes that are interpreted as source + * files. + */ +void +nse_init_source_suffixes(void) +{ + FILE *fp; + wchar_t suffix[100]; + Nse_suffix sufx; + Nse_suffix *bpatch; + + fp = fopen(TARG_SUFX, "r"); + if (fp == NULL) { + return; + } + bpatch = &sufx_hdr; + while (fscanf(fp, "%s %*s", suffix) == 1) { +#ifdef SUNOS4_AND_AFTER + sufx = ALLOC(Nse_suffix); + sufx->suffix = wscpy(ALLOC_WC(wslen(suffix) + 1), suffix); +#else + sufx = alloc(Nse_suffix); + sufx->suffix = strcpy(malloc(strlen(suffix) + 1), suffix); +#endif + sufx->next = NULL; + *bpatch = sufx; + bpatch = &sufx->next; + } + fclose(fp); +} + +/* + * Check if a derived file (something with a dependency) appears + * to be a source file (by its suffix) but has no rule to build it. + * If so, complain. + * + * This generally arises from the old-style of make-depend that + * produces: + * foo.c: foo.h + */ +void +nse_check_derived_src(Name target, wchar_t *dep, Cmd_line command_template) +{ + Nse_suffix sufx; + wchar_t *suffix; + wchar_t *depsufx; + +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } +#ifdef SUNOS4_AND_AFTER + if (target->stat.is_derived_src) { +#else + if (is_true(target->stat.is_derived_src)) { +#endif + return; + } + if (command_template != NULL) { + return; + } +#ifdef SUNOS4_AND_AFTER + suffix = wsrchr(target->string, (int) period_char ); +#else + suffix = rindex(target->string, '.'); +#endif + if (suffix != NULL) { + for (sufx = sufx_hdr; sufx != NULL; sufx = sufx->next) { +#ifdef SUNOS4_AND_AFTER + if (IS_WEQUAL(sufx->suffix, suffix)) { +#else + if (is_equal(sufx->suffix, suffix)) { +#endif + nse_warning(); + WCSTOMBS(mbs_buffer, dep); + fprintf(stderr, "\tProbable source file `%s' appears as a derived file\n\tas it depends upon file `%s', but there is\n\tno rule to build it\n", + target->string_mb, mbs_buffer); + break; + } + } + } +} + +/* + * See if a target is a potential source file and has no + * dependencies and no rule but shows up on the right-hand + * side. This tends to occur from old "make depend" output. + */ +void +nse_check_no_deps_no_rule(Name target, Property line, Property command) +{ + Nse_suffix sufx; + wchar_t *suffix; + +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } +#ifdef SUNOS4_AND_AFTER + if (target->stat.is_derived_src) { +#else + if (is_true(target->stat.is_derived_src)) { +#endif + return; + } + if (line != NULL && line->body.line.dependencies != NULL) { + return; + } +#ifdef SUNOS4_AND_AFTER + if (command->body.line.sccs_command) { +#else + if (is_true(command->body.line.sccs_command)) { +#endif + return; + } +#ifdef SUNOS4_AND_AFTER + suffix = wsrchr(target->string, (int) period_char); +#else + suffix = rindex(target->string, '.'); +#endif + if (suffix != NULL) { + for (sufx = sufx_hdr; sufx != NULL; sufx = sufx->next) { +#ifdef SUNOS4_AND_AFTER + if (IS_WEQUAL(sufx->suffix, suffix)) { +#else + if (is_equal(sufx->suffix, suffix)) { +#endif + if (command->body.line.command_template == NULL) { + nse_warning(); + fprintf(stderr, "\tProbable source file `%s' appears as a derived file because\n\tit is on the left-hand side, but it has no dependencies and\n\tno rule to build it\n", + target->string_mb); + } + } + } + } +} + +/* + * Detected a situation where a recursive make derived a file + * without using a makefile. + */ +void +nse_no_makefile(Name target) +{ +#ifdef SUNOS4_AND_AFTER + if (!nse) { +#else + if (is_false(flag.nse)) { +#endif + return; + } + nse_warning(); + fprintf(stderr, "Recursive make to derive %s did not use a makefile\n", + target->string_mb); +} + +/* + * Return the NSE exit status. + * If the -P flag was given then a warning is considered fatal + */ +int +nse_exit_status(void) +{ + return our_exit_status; +} +#endif diff --git a/usr/src/make_src/Make/bin/make/common/nse_printdep.cc b/usr/src/make_src/Make/bin/make/common/nse_printdep.cc new file mode 100644 index 0000000..cda02f8 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/nse_printdep.cc @@ -0,0 +1,517 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)nse_printdep.cc 1.18 06/12/12 + */ + +#pragma ident "@(#)nse_printdep.cc 1.18 06/12/12" + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/misc.h> /* get_prop() */ + +/* + * File table of contents + */ +void print_dependencies(register Name target, register Property line); +static void print_deps(register Name target, register Property line); +static void print_more_deps(Name target, Name name); +static void print_filename(Name name); +static Boolean should_print_dep(Property line); +static void print_forest(Name target); +static void print_deplist(Dependency head); +void print_value(register Name value, Daemon daemon); +static void print_rule(register Name target); +static void print_rec_info(Name target); +static Boolean is_out_of_date(Property line); +extern void depvar_print_results (void); +extern int printf (const char *, ...); +extern int _flsbuf (unsigned int, FILE *); + +/* + * print_dependencies(target, line) + * + * Print all the dependencies of a target. First print all the Makefiles. + * Then print all the dependencies. Finally, print all the .INIT + * dependencies. + * + * Parameters: + * target The target we print dependencies for + * line We get the dependency list from here + * + * Global variables used: + * done The Name ".DONE" + * init The Name ".INIT" + * makefiles_used List of all makefiles read + */ +void +print_dependencies(register Name target, register Property line) +{ + Dependency dp; + static Boolean makefiles_printed = false; + +#ifdef SUNOS4_AND_AFTER + if (target_variants) { +#else + if (is_true(flag.target_variants)) { +#endif + depvar_print_results(); + } + + if (!makefiles_printed) { + /* + * Search the makefile list for the primary makefile, + * then print it and its inclusions. After that go back + * and print the default.mk file and its inclusions. + */ + for (dp = makefiles_used; dp != NULL; dp = dp->next) { + if (dp->name == primary_makefile) { + break; + } + } + if (dp) { + print_deplist(dp); + for (dp = makefiles_used; dp != NULL; dp = dp->next) { + if (dp->name == primary_makefile) { + break; + } + (void)printf(" %s", dp->name->string_mb); + } + } + (void) printf("\n"); + makefiles_printed = true; + } + print_deps(target, line); +#ifdef SUNOS4_AND_AFTER +/* + print_more_deps(target, init); + print_more_deps(target, done); + */ + if (target_variants) { +#else + print_more_deps(target, cached_names.init); + print_more_deps(target, cached_names.done); + if (is_true(flag.target_variants)) { +#endif + print_forest(target); + } +} + +/* + * print_more_deps(target, name) + * + * Print some special dependencies. + * These are the dependencies for the .INIT and .DONE targets. + * + * Parameters: + * target Target built during make run + * name Special target to print dependencies for + * + * Global variables used: + */ +static void +print_more_deps(Name target, Name name) +{ + Property line; + register Dependency dependencies; + + line = get_prop(name->prop, line_prop); + if (line != NULL && line->body.line.dependencies != NULL) { + (void) printf("%s:\t", target->string_mb); + print_deplist(line->body.line.dependencies); + (void) printf("\n"); + for (dependencies= line->body.line.dependencies; + dependencies != NULL; + dependencies= dependencies->next) { + print_deps(dependencies->name, + get_prop(dependencies->name->prop, line_prop)); + } + } +} + +/* + * print_deps(target, line, go_recursive) + * + * Print a regular dependency list. Append to this information which + * indicates whether or not the target is recursive. + * + * Parameters: + * target target to print dependencies for + * line We get the dependency list from here + * go_recursive Should we show all dependencies recursively? + * + * Global variables used: + * recursive_name The Name ".RECURSIVE", printed + */ +static void +print_deps(register Name target, register Property line) +{ + register Dependency dep; + +#ifdef SUNOS4_AND_AFTER + if ((target->dependency_printed) || + (target == force)) { +#else + if (is_true(target->dependency_printed)) { +#endif + return; + } + target->dependency_printed = true; + + /* only print entries that are actually derived and are not leaf + * files and are not the result of sccs get. + */ + if (should_print_dep(line)) { +#ifdef NSE + nse_check_no_deps_no_rule(target, line, line); +#endif + if ((report_dependencies_level == 2) || + (report_dependencies_level == 4)) { + if (is_out_of_date(line)) { + (void) printf("1 "); + } else { + (void) printf("0 "); + } + } + print_filename(target); + (void) printf(":\t"); + print_deplist(line->body.line.dependencies); + print_rec_info(target); + (void) printf("\n"); + for (dep = line->body.line.dependencies; + dep != NULL; + dep = dep->next) { + print_deps(dep->name, + get_prop(dep->name->prop, line_prop)); + } + } +} + +static Boolean +is_out_of_date(Property line) +{ + Dependency dep; + Property line2; + + if (line == NULL) { + return false; + } + if (line->body.line.is_out_of_date) { + return true; + } + for (dep = line->body.line.dependencies; + dep != NULL; + dep = dep->next) { + line2 = get_prop(dep->name->prop, line_prop); + if (is_out_of_date(line2)) { + line->body.line.is_out_of_date = true; + return true; + } + } + return false; +} + +/* + * Given a dependency print it and all its siblings. + */ +static void +print_deplist(Dependency head) +{ + Dependency dp; + + for (dp = head; dp != NULL; dp = dp->next) { + if ((report_dependencies_level != 2) || + ((!dp->automatic) || + (dp->name->is_double_colon))) { + if (dp->name != force) { + putwchar(' '); + print_filename(dp->name); + } + } + } +} + +/* + * Print the name of a file for the -P option. + * If the file is a directory put on a trailing slash. + */ +static void +print_filename(Name name) +{ + (void) printf("%s", name->string_mb); +/* + if (name->stat.is_dir) { + putwchar('/'); + } + */ +} + +/* + * should_print_dep(line) + * + * Test if we should print the dependencies of this target. + * The line must exist and either have children dependencies + * or have a command that is not an SCCS command. + * + * Return value: + * true if the dependencies should be printed + * + * Parameters: + * line We get the dependency list from here + * + * Global variables used: + */ +static Boolean +should_print_dep(Property line) +{ + if (line == NULL) { + return false; + } + if (line->body.line.dependencies != NULL) { + return true; + } +#ifdef SUNOS4_AND_AFTER + if (line->body.line.sccs_command) { +#else + if (is_true(line->body.line.sccs_command)) { +#endif + return false; + } + return true; +} + +/* + * Print out the root nodes of all the dependency trees + * in this makefile. + */ +static void +print_forest(Name target) +{ + Name_set::iterator np, e; + Property line; + + for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) { +#ifdef SUNOS4_AND_AFTER + if (np->is_target && !np->has_parent && np != target) { +#else + if (is_true(np->is_target) && + is_false(np->has_parent) && + np != target) { +#endif + (void) doname_check(np, true, false, false); + line = get_prop(np->prop, line_prop); + printf("-\n"); + print_deps(np, line); + } + } +} + +#ifndef SUNOS4_AND_AFTER +printdesc() +{ + Name_set::iterator p, e; + register Property prop; + register Dependency dep; + register Cmd_line rule; + Percent percent, percent_depe; + + /* Default target */ + if (default_target_to_build != NULL) { + print_rule(default_target_to_build); + default_target_to_build->dependency_printed= true; + }; + (void)printf("\n"); + + /* .AR_REPLACE */ + if (ar_replace_rule != NULL) { + (void)printf("%s:\n", cached_names.ar_replace->string_mb); + for (rule= ar_replace_rule; rule != NULL; rule= rule->next) + (void)printf("\t%s\n", rule->command_line->string_mb); + }; + + /* .DEFAULT */ + if (default_rule != NULL) { + (void)printf("%s:\n", cached_names.default_rule->string_mb); + for (rule= default_rule; rule != NULL; rule= rule->next) + (void)printf("\t%s\n", rule->command_line->string_mb); + }; + + /* .IGNORE */ + if (is_true(flag.ignore_errors)) + (void)printf("%s:\n", cached_names.ignore->string_mb); + + /* .KEEP_STATE: */ + if (is_true(flag.keep_state)) + (void)printf("%s:\n\n", cached_names.dot_keep_state->string_mb); + + /* .PRECIOUS */ + (void)printf("%s: ", cached_names.precious->string_mb); + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) + if (is_true(p->stat.is_precious | all_precious)) + (void)printf("%s ", p->string_mb); + (void)printf("\n"); + + /* .SCCS_GET */ + if (sccs_get_rule != NULL) { + (void)printf("%s:\n", cached_names.sccs_get->string_mb); + for (rule= sccs_get_rule; rule != NULL; rule= rule->next) + (void)printf("\t%s\n", rule->command_line->string_mb); + }; + + /* .SILENT */ + if (is_true(flag.silent)) + (void)printf("%s:\n", cached_names.silent->string_mb); + + /* .SUFFIXES: */ + (void)printf("%s: ", cached_names.suffixes->string_mb); + for (dep= suffixes; dep != NULL; dep= dep->next) { + (void)printf("%s ", dep->name->string_mb); + build_suffix_list(dep->name); + }; + (void)printf("\n\n"); + + /* % rules */ + for (percent= percent_list; percent != NULL; percent= percent->next) { + (void) printf("%s:", percent->name->string_mb); + + for (percent_depe= percent->dependencies; percent_depe != NULL; percent_depe = percent_depe->next) + (void) printf(" %s", percent_depe->name->string_mb); + + (void) printf("\n"); + + for (rule= percent->command_template; rule != NULL; rule= rule->next) + (void)printf("\t%s\n", rule->command_line->string_mb); + }; + + /* Suffix rules */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) + if (is_false(p->dependency_printed) && (p->string[0] == PERIOD)) { + print_rule(p); + p->dependency_printed= true; + }; + + /* Macro assignments */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) + if (((prop= get_prop(p->prop, macro_prop)) != NULL) && + (prop->body.macro.value != NULL)) { + (void)printf("%s", p->string_mb); + print_value(prop->body.macro.value, + prop->body.macro.daemon); + }; + (void)printf("\n"); + + /* Delays */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) + for (prop= get_prop(p->prop, conditional_prop); + prop != NULL; + prop= get_prop(prop->next, conditional_prop)) { + (void)printf("%s := %s", + p->string_mb, + prop->body.conditional.name->string_mb); + print_value(prop->body.conditional.value, no_daemon); + }; + (void)printf("\n"); + + /* All other dependencies */ + for (p = hashtab.begin(), e = hashtab.end(); p != e; p++) + if (is_false(p->dependency_printed) && (p->colons != no_colon)) + print_rule(p); + (void)printf("\n"); + exit(0); +} +#endif + +/* + * This is a set of routines for dumping the internal make state + * Used for the -p option + */ +void +print_value(register Name value, Daemon daemon) + +#ifdef SUNOS4_AND_AFTER + +#else + +#endif +{ + Chain cp; + + if (value == NULL) + (void)printf("=\n"); + else + switch (daemon) { + case no_daemon: + (void)printf("= %s\n", value->string_mb); + break; + case chain_daemon: + for (cp= (Chain) value; cp != NULL; cp= cp->next) + (void)printf(cp->next == NULL ? "%s" : "%s ", + cp->name->string_mb); + (void)printf("\n"); + break; + }; +} + +static void +print_rule(register Name target) +{ + register Cmd_line rule; + register Property line; + + if (((line= get_prop(target->prop, line_prop)) == NULL) || + ((line->body.line.command_template == NULL) && + (line->body.line.dependencies == NULL))) + return; + print_dependencies(target, line); + for (rule= line->body.line.command_template; rule != NULL; rule= rule->next) + (void)printf("\t%s\n", rule->command_line->string_mb); +} + + +/* + * If target is recursive, print the following to standard out: + * .RECURSIVE subdir targ Makefile + */ +static void +print_rec_info(Name target) +{ + Recursive_make rp; + wchar_t *colon; + + report_recursive_init(); + + rp = find_recursive_target(target); + + if (rp) { + /* + * if found, print starting with the space after the ':' + */ + colon = (wchar_t *) wschr(rp->oldline, (int) colon_char); + (void) printf("%s", colon + 1); + } +} + diff --git a/usr/src/make_src/Make/bin/make/common/parallel.cc b/usr/src/make_src/Make/bin/make/common/parallel.cc new file mode 100644 index 0000000..1831415 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/parallel.cc @@ -0,0 +1,2477 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)parallel.cc 1.75 06/12/12 + */ + +#pragma ident "@(#)parallel.cc 1.75 06/12/12" + +#ifdef TEAMWARE_MAKE_CMN + +/* + * parallel.cc + * + * Deal with the parallel processing + */ + +/* + * Included files + */ +#ifdef DISTRIBUTED +#include <avo/strings.h> /* AVO_STRDUP() */ +#include <dm/Avo_DoJobMsg.h> +#include <dm/Avo_MToolJobResultMsg.h> +#endif +#include <errno.h> /* errno */ +#include <fcntl.h> +#include <avo/util.h> /* avo_get_user(), avo_hostname() */ +#include <mk/defs.h> +#include <mksh/dosys.h> /* redirect_io() */ +#include <mksh/macro.h> /* expand_value() */ +#include <mksh/misc.h> /* getmem() */ +#include <sys/signal.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <sys/wait.h> +#include <unistd.h> + +#ifdef SGE_SUPPORT +#include <dmthread/Avo_PathNames.h> +#endif + + +/* + * Defined macros + */ +#define MAXRULES 100 + +/* + * This const should be in avo_dms/include/AvoDmakeCommand.h + */ +const int local_host_mask = 0x20; + + +/* + * typedefs & structs + */ + + +/* + * Static variables + */ +#ifdef TEAMWARE_MAKE_CMN +static Boolean just_did_subtree = false; +static char local_host[MAXNAMELEN] = ""; +static char user_name[MAXNAMELEN] = ""; +#endif +static int pmake_max_jobs = 0; +static pid_t process_running = -1; +static Running *running_tail = &running_list; +static Name subtree_conflict; +static Name subtree_conflict2; + + +/* + * File table of contents + */ +#ifdef DISTRIBUTED +static void append_dmake_cmd(Avo_DoJobMsg *dmake_job_msg, char *orig_cmd_line, int cmd_options); +static void append_job_result_msg(Avo_MToolJobResultMsg *msg, char *outFn, char *errFn); +static void send_job_result_msg(Running rp); +#endif +static void delete_running_struct(Running rp); +static Boolean dependency_conflict(Name target); +static Doname distribute_process(char **commands, Property line); +static void doname_subtree(Name target, Boolean do_get, Boolean implicit); +static void dump_out_file(char *filename, Boolean err); +static void finish_doname(Running rp); +static void maybe_reread_make_state(void); +static void process_next(void); +static void reset_conditionals(int cnt, Name *targets, Property *locals); +static pid_t run_rule_commands(char *host, char **commands); +static Property *set_conditionals(int cnt, Name *targets); +static void store_conditionals(Running rp); + + +/* + * execute_parallel(line, waitflg) + * + * DMake 2.x: + * parallel mode: spawns a parallel process to execute the command group. + * distributed mode: sends the command group down the pipe to rxm. + * + * Return value: + * The result of the execution + * + * Parameters: + * line The command group to execute + */ +Doname +execute_parallel(Property line, Boolean waitflg, Boolean local) +{ + int argcnt; + int cmd_options = 0; + char *commands[MAXRULES + 5]; + char *cp; +#ifdef DISTRIBUTED + Avo_DoJobMsg *dmake_job_msg = NULL; +#endif + Name dmake_name; + Name dmake_value; + int ignore; + Name make_machines_name; + char **p; + Property prop; + Doname result = build_ok; + Cmd_line rule; + Boolean silent_flag; + Name target = line->body.line.target; + Boolean wrote_state_file = false; + + if ((pmake_max_jobs == 0) && + (dmake_mode_type == parallel_mode)) { + if (user_name[0] == '\0') { + avo_get_user(user_name, NULL); + } + if (local_host[0] == '\0') { + strcpy(local_host, avo_hostname()); + } + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_MAX_JOBS")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + pmake_max_jobs = atoi(dmake_value->string_mb); + if (pmake_max_jobs <= 0) { + warning(catgets(catd, 1, 308, "DMAKE_MAX_JOBS cannot be less than or equal to zero.")); + warning(catgets(catd, 1, 309, "setting DMAKE_MAX_JOBS to %d."), PMAKE_DEF_MAX_JOBS); + pmake_max_jobs = PMAKE_DEF_MAX_JOBS; + } + } else { + /* + * For backwards compatibility w/ PMake 1.x, when + * DMake 2.x is being run in parallel mode, DMake + * should parse the PMake startup file + * $(HOME)/.make.machines to get the pmake_max_jobs. + */ + MBSTOWCS(wcs_buffer, NOCATGETS("PMAKE_MACHINESFILE")); + dmake_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmake_name->prop, macro_prop)) != NULL) && + ((dmake_value = prop->body.macro.value) != NULL)) { + make_machines_name = dmake_value; + } else { + make_machines_name = NULL; + } + if ((pmake_max_jobs = read_make_machines(make_machines_name)) <= 0) { + pmake_max_jobs = PMAKE_DEF_MAX_JOBS; + } + } +#ifdef DISTRIBUTED + if (send_mtool_msgs) { + send_rsrc_info_msg(pmake_max_jobs, local_host, user_name); + } +#endif + } + + if ((dmake_mode_type == serial_mode) || + ((dmake_mode_type == parallel_mode) && (waitflg))) { + return (execute_serial(line)); + } + +#ifdef DISTRIBUTED + if (dmake_mode_type == distributed_mode) { + if(local) { +// return (execute_serial(line)); + waitflg = true; + } + dmake_job_msg = new Avo_DoJobMsg(); + dmake_job_msg->setJobId(++job_msg_id); + dmake_job_msg->setTarget(target->string_mb); + dmake_job_msg->setImmediateOutput(0); + called_make = false; + } else +#endif + { + p = commands; + } + + argcnt = 0; + for (rule = line->body.line.command_used; + rule != NULL; + rule = rule->next) { + if (posix && (touch || quest) && !rule->always_exec) { + continue; + } + if (vpath_defined) { + rule->command_line = + vpath_translation(rule->command_line); + } + if (dmake_mode_type == distributed_mode) { + cmd_options = 0; + if(local) { + cmd_options |= local_host_mask; + } + } else { + silent_flag = false; + ignore = 0; + } + if (rule->command_line->hash.length > 0) { + if (++argcnt == MAXRULES) { + if (dmake_mode_type == distributed_mode) { + /* XXX - tell rxm to execute on local host. */ + /* I WAS HERE!!! */ + } else { + /* Too many rules, run serially instead. */ + return build_serial; + } + } +#ifdef DISTRIBUTED + if (dmake_mode_type == distributed_mode) { + /* + * XXX - set assign_mask to tell rxm + * to do the following. + */ +/* From execute_serial(): + if (rule->assign) { + result = build_ok; + do_assign(rule->command_line, target); + */ + if (0) { + } else if (report_dependencies_level == 0) { + if (rule->ignore_error) { + cmd_options |= ignore_mask; + } + if (rule->silent) { + cmd_options |= silent_mask; + } + if (rule->command_line->meta) { + cmd_options |= meta_mask; + } + if (rule->make_refd) { + cmd_options |= make_refd_mask; + } + if (do_not_exec_rule) { + cmd_options |= do_not_exec_mask; + } + append_dmake_cmd(dmake_job_msg, + rule->command_line->string_mb, + cmd_options); + /* Copying dosys()... */ + if (rule->make_refd) { + if (waitflg) { + dmake_job_msg->setImmediateOutput(1); + } + called_make = true; + if (command_changed && + !wrote_state_file) { + write_state_file(0, false); + wrote_state_file = true; + } + } + } + } else +#endif + { + if (rule->silent && !silent) { + silent_flag = true; + } + if (rule->ignore_error) { + ignore++; + } + /* XXX - need to add support for + prefix */ + if (silent_flag || ignore) { + *p = getmem((silent_flag ? 1 : 0) + + ignore + + (strlen(rule-> + command_line-> + string_mb)) + + 1); + cp = *p++; + if (silent_flag) { + *cp++ = (int) at_char; + } + if (ignore) { + *cp++ = (int) hyphen_char; + } + (void) strcpy(cp, rule->command_line->string_mb); + } else { + *p++ = rule->command_line->string_mb; + } + } + } + } + if ((argcnt == 0) || + (report_dependencies_level > 0)) { +#ifdef DISTRIBUTED + if (dmake_job_msg) { + delete dmake_job_msg; + } +#endif + return build_ok; + } +#ifdef DISTRIBUTED + if (dmake_mode_type == distributed_mode) { + // Send a DoJob message to the rxm process. + distribute_rxm(dmake_job_msg); + + // Wait for an acknowledgement. + Avo_AcknowledgeMsg *ackMsg = getAcknowledgeMsg(); + if (ackMsg) { + delete ackMsg; + } + + if (waitflg) { + // Wait for, and process a job result. + result = await_dist(waitflg); + if (called_make) { + maybe_reread_make_state(); + } + check_state(temp_file_name); + if (result == build_failed) { + if (!continue_after_error) { + +#ifdef PRINT_EXIT_STATUS + warning(NOCATGETS("I'm in execute_parallel. await_dist() returned build_failed")); +#endif + + fatal(catgets(catd, 1, 252, "Command failed for target `%s'"), + target->string_mb); + } + /* + * Make sure a failing command is not + * saved in .make.state. + */ + line->body.line.command_used = NULL; + } + if (temp_file_name != NULL) { + free_name(temp_file_name); + } + temp_file_name = NULL; + Property spro = get_prop(sunpro_dependencies->prop, macro_prop); + if(spro != NULL) { + Name val = spro->body.macro.value; + if(val != NULL) { + free_name(val); + spro->body.macro.value = NULL; + } + } + spro = get_prop(sunpro_dependencies->prop, env_mem_prop); + if(spro) { + char *val = spro->body.env_mem.value; + if(val != NULL) { + retmem_mb(val); + spro->body.env_mem.value = NULL; + } + } + return result; + } else { + parallel_process_cnt++; + return build_running; + } + } else +#endif + { + *p = NULL; + + Doname res = distribute_process(commands, line); + if (res == build_running) { + parallel_process_cnt++; + } + + /* + * Return only those memory that were specially allocated + * for part of commands. + */ + for (int i = 0; commands[i] != NULL; i++) { + if ((commands[i][0] == (int) at_char) || + (commands[i][0] == (int) hyphen_char)) { + retmem_mb(commands[i]); + } + } + return res; + } +} + +#ifdef DISTRIBUTED +/* + * append_dmake_cmd() + * + * Replaces all escaped newline's (\<cr>) + * in the original command line with space's, + * then append the new command line to the DoJobMsg object. + */ +static void +append_dmake_cmd(Avo_DoJobMsg *dmake_job_msg, + char *orig_cmd_line, + int cmd_options) +{ +/* + Avo_DmakeCommand *tmp_dmake_command; + + tmp_dmake_command = new Avo_DmakeCommand(orig_cmd_line, cmd_options); + dmake_job_msg->appendCmd(tmp_dmake_command); + delete tmp_dmake_command; + */ + dmake_job_msg->appendCmd(new Avo_DmakeCommand(orig_cmd_line, cmd_options)); +} +#endif + +#ifdef TEAMWARE_MAKE_CMN +#define MAXJOBS_ADJUST_RFE4694000 + +#ifdef MAXJOBS_ADJUST_RFE4694000 + +#include <unistd.h> /* sysconf(_SC_NPROCESSORS_ONLN) */ +#include <sys/ipc.h> /* ftok() */ +#include <sys/shm.h> /* shmget(), shmat(), shmdt(), shmctl() */ +#include <semaphore.h> /* sem_init(), sem_trywait(), sem_post(), sem_destroy() */ +#if defined(linux) +#define LOADAVG_1MIN 0 +#else +#include <sys/loadavg.h> /* getloadavg() */ +#endif /* linux */ + +/* + * adjust_pmake_max_jobs (int pmake_max_jobs) + * + * Parameters: + * pmake_max_jobs - max jobs limit set by user + * + * External functions used: + * sysconf() + * getloadavg() + */ +static int +adjust_pmake_max_jobs (int pmake_max_jobs) +{ + static int ncpu = 0; + double loadavg[3]; + int adjustment; + int adjusted_max_jobs; + + if (ncpu <= 0) { + if ((ncpu = sysconf(_SC_NPROCESSORS_ONLN)) <= 0) { + ncpu = 1; + } + } + if (getloadavg(loadavg, 3) != 3) return(pmake_max_jobs); + adjustment = ((int)loadavg[LOADAVG_1MIN]); + if (adjustment < 2) return(pmake_max_jobs); + if (ncpu > 1) { + adjustment = adjustment / ncpu; + } + adjusted_max_jobs = pmake_max_jobs - adjustment; + if (adjusted_max_jobs < 1) adjusted_max_jobs = 1; + return(adjusted_max_jobs); +} + +/* + * M2 adjust mode data and functions + * + * m2_init() - initializes M2 shared semaphore + * m2_acquire_job() - decrements M2 semaphore counter + * m2_release_job() - increments M2 semaphore counter + * m2_fini() - destroys M2 semaphore and shared memory* + * + * Environment variables: + * __DMAKE_M2_FILE__ + * + * External functions: + * ftok(), shmget(), shmat(), shmdt(), shmctl() + * sem_init(), sem_trywait(), sem_post(), sem_destroy() + * creat(), close(), unlink() + * getenv(), putenv() + * + * Static variables: + * m2_file - tmp file name to create ipc key for shared memory + * m2_shm_id - shared memory id + * m2_shm_sem - shared memory semaphore + */ + +static char m2_file[MAXPATHLEN]; +static int m2_shm_id = -1; +static sem_t* m2_shm_sem = 0; + +static int +m2_init() { + char *var; + key_t key; + + if ((var = getenv(NOCATGETS("__DMAKE_M2_FILE__"))) == 0) { + /* compose tmp file name */ + sprintf(m2_file, NOCATGETS("%s/dmake.m2.%d.XXXXXX"), tmpdir, getpid()); + + /* create tmp file */ + int fd = mkstemp(m2_file); + if (fd < 0) { + return -1; + } else { + close(fd); + } + } else { + /* using existing semaphore */ + strcpy(m2_file, var); + } + + /* combine IPC key */ + if ((key = ftok(m2_file, 38)) == (key_t) -1) { + return -1; + } + + /* create shared memory */ + if ((m2_shm_id = shmget(key, sizeof(*m2_shm_sem), 0666 | (var ? 0 : IPC_CREAT|IPC_EXCL))) == -1) { + return -1; + } + + /* attach shared memory */ + if ((m2_shm_sem = (sem_t*) shmat(m2_shm_id, 0, 0666)) == (sem_t*)-1) { + return -1; + } + + /* root process */ + if (var == 0) { + /* initialize semaphore */ + if (sem_init(m2_shm_sem, 1, pmake_max_jobs)) { + return -1; + } + + /* alloc memory for env variable */ + if ((var = (char*) malloc(MAXPATHLEN)) == 0) { + return -1; + } + + /* put key to env */ + sprintf(var, NOCATGETS("__DMAKE_M2_FILE__=%s"), m2_file); + if (putenv(var)) { + return -1; + } + } + return 0; +} + +static void +m2_fini() { + if (m2_shm_id >= 0) { + struct shmid_ds stat; + + /* determine the number of attached processes */ + if (shmctl(m2_shm_id, IPC_STAT, &stat) == 0) { + if (stat.shm_nattch <= 1) { + /* destroy semaphore */ + if (m2_shm_sem != 0) { + (void) sem_destroy(m2_shm_sem); + } + + /* destroy shared memory */ + (void) shmctl(m2_shm_id, IPC_RMID, &stat); + + /* remove tmp file created for the key */ + (void) unlink(m2_file); + } else { + /* detach shared memory */ + if (m2_shm_sem != 0) { + (void) shmdt((char*) m2_shm_sem); + } + } + } + + m2_shm_id = -1; + m2_shm_sem = 0; + } +} + +static int +m2_acquire_job() { + if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) { + if (sem_trywait(m2_shm_sem) == 0) { + return 1; + } + if (errno == EAGAIN) { + return 0; + } + } + return -1; +} + +static int +m2_release_job() { + if ((m2_shm_id >= 0) && (m2_shm_sem != 0)) { + if (sem_post(m2_shm_sem) == 0) { + return 0; + } + } + return -1; +} + +/* + * job adjust mode + * + * Possible values: + * ADJUST_M1 - adjustment by system load (default) + * ADJUST_M2 - fixed limit of jobs for the group of nested dmakes + * ADJUST_NONE - no adjustment - fixed limit of jobs for the current dmake + */ +static enum { + ADJUST_UNKNOWN, + ADJUST_M1, + ADJUST_M2, + ADJUST_NONE +} job_adjust_mode = ADJUST_UNKNOWN; + +/* + * void job_adjust_fini() + * + * Description: + * Cleans up job adjust data. + * + * Static variables: + * job_adjust_mode Current job adjust mode + */ +void +job_adjust_fini() { + if (job_adjust_mode == ADJUST_M2) { + m2_fini(); + } +} + +/* + * void job_adjust_error() + * + * Description: + * Prints warning message, cleans up job adjust data, and disables job adjustment + * + * Environment: + * DMAKE_ADJUST_MAX_JOBS + * + * External functions: + * putenv() + * + * Static variables: + * job_adjust_mode Current job adjust mode + */ +static void +job_adjust_error() { + if (job_adjust_mode != ADJUST_NONE) { + /* cleanup internals */ + job_adjust_fini(); + + /* warning message for the user */ + warning(catgets(catd, 1, 339, "Encountered max jobs auto adjustment error - disabling auto adjustment.")); + + /* switch off job adjustment for the children */ + putenv(NOCATGETS("DMAKE_ADJUST_MAX_JOBS=NO")); + + /* and for this dmake */ + job_adjust_mode = ADJUST_NONE; + } +} + +/* + * void job_adjust_init() + * + * Description: + * Parses DMAKE_ADJUST_MAX_JOBS env variable + * and performs appropriate initializations. + * + * Environment: + * DMAKE_ADJUST_MAX_JOBS + * DMAKE_ADJUST_MAX_JOBS == "NO" - no adjustment + * DMAKE_ADJUST_MAX_JOBS == "M2" - M2 adjust mode + * other - M1 adjust mode + * + * External functions: + * getenv() + * + * Static variables: + * job_adjust_mode Current job adjust mode + */ +static void +job_adjust_init() { + if (job_adjust_mode == ADJUST_UNKNOWN) { + /* default mode */ + job_adjust_mode = ADJUST_M1; + + /* determine adjust mode */ + if (char *var = getenv(NOCATGETS("DMAKE_ADJUST_MAX_JOBS"))) { + if (strcasecmp(var, NOCATGETS("NO")) == 0) { + job_adjust_mode = ADJUST_NONE; + } else if (strcasecmp(var, NOCATGETS("M2")) == 0) { + job_adjust_mode = ADJUST_M2; + } + } + + /* M2 specific initialization */ + if (job_adjust_mode == ADJUST_M2) { + if (m2_init()) { + job_adjust_error(); + } + } + } +} + +#endif /* MAXJOBS_ADJUST_RFE4694000 */ +#endif /* TEAMWARE_MAKE_CMN */ + +/* + * distribute_process(char **commands, Property line) + * + * Parameters: + * commands argv vector of commands to execute + * + * Return value: + * The result of the execution + * + * Static variables used: + * process_running Set to the pid of the process set running + * #if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000) + * job_adjust_mode Current job adjust mode + * #endif + */ +static Doname +distribute_process(char **commands, Property line) +{ + static unsigned file_number = 0; + wchar_t string[MAXPATHLEN]; + char mbstring[MAXPATHLEN]; + int filed; + int res; + int tmp_index; + char *tmp_index_str_ptr; + +#if !defined (TEAMWARE_MAKE_CMN) || !defined (MAXJOBS_ADJUST_RFE4694000) + while (parallel_process_cnt >= pmake_max_jobs) { + await_parallel(false); + finish_children(true); + } +#else /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */ + /* initialize adjust mode, if not initialized */ + if (job_adjust_mode == ADJUST_UNKNOWN) { + job_adjust_init(); + } + + /* actions depend on adjust mode */ + switch (job_adjust_mode) { + case ADJUST_M1: + while (parallel_process_cnt >= adjust_pmake_max_jobs (pmake_max_jobs)) { + await_parallel(false); + finish_children(true); + } + break; + case ADJUST_M2: + if ((res = m2_acquire_job()) == 0) { + if (parallel_process_cnt > 0) { + await_parallel(false); + finish_children(true); + + if ((res = m2_acquire_job()) == 0) { + return build_serial; + } + } else { + return build_serial; + } + } + if (res < 0) { + /* job adjustment error */ + job_adjust_error(); + + /* no adjustment */ + while (parallel_process_cnt >= pmake_max_jobs) { + await_parallel(false); + finish_children(true); + } + } + break; + default: + while (parallel_process_cnt >= pmake_max_jobs) { + await_parallel(false); + finish_children(true); + } + } +#endif /* TEAMWARE_MAKE_CMN && MAXJOBS_ADJUST_RFE4694000 */ +#ifdef DISTRIBUTED + if (send_mtool_msgs) { + send_job_start_msg(line); + } +#endif +#ifdef DISTRIBUTED + setvar_envvar((Avo_DoJobMsg *)NULL); +#else + setvar_envvar(); +#endif + /* + * Tell the user what DMake is doing. + */ + if (!silent && output_mode != txt2_mode) { + /* + * Print local_host --> x job(s). + */ + (void) fprintf(stdout, + catgets(catd, 1, 325, "%s --> %d %s\n"), + local_host, + parallel_process_cnt + 1, + (parallel_process_cnt == 0) ? catgets(catd, 1, 124, "job") : catgets(catd, 1, 125, "jobs")); + + /* Print command line(s). */ + tmp_index = 0; + while (commands[tmp_index] != NULL) { + /* No @ char. */ + /* XXX - need to add [2] when + prefix is added */ + if ((commands[tmp_index][0] != (int) at_char) && + (commands[tmp_index][1] != (int) at_char)) { + tmp_index_str_ptr = commands[tmp_index]; + if (*tmp_index_str_ptr == (int) hyphen_char) { + tmp_index_str_ptr++; + } + (void) fprintf(stdout, "%s\n", tmp_index_str_ptr); + } + tmp_index++; + } + (void) fflush(stdout); + } + + (void) sprintf(mbstring, + NOCATGETS("%s/dmake.stdout.%d.%d.XXXXXX"), + tmpdir, + getpid(), + file_number++); + + mktemp(mbstring); + + stdout_file = strdup(mbstring); + stderr_file = NULL; +#if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR) + if (!out_err_same) { + (void) sprintf(mbstring, + NOCATGETS("%s/dmake.stderr.%d.%d.XXXXXX"), + tmpdir, + getpid(), + file_number++); + + mktemp(mbstring); + + stderr_file = strdup(mbstring); + } +#endif + +#ifdef SGE_SUPPORT + if (grid) { + static char *dir4gridscripts = NULL; + static char *hostName = NULL; + if (dir4gridscripts == NULL) { + Name dmakeOdir_name, dmakeOdir_value; + Property prop; + MBSTOWCS(wcs_buffer, NOCATGETS("DMAKE_ODIR")); + dmakeOdir_name = GETNAME(wcs_buffer, FIND_LENGTH); + if (((prop = get_prop(dmakeOdir_name->prop, macro_prop)) != NULL) && + ((dmakeOdir_value = prop->body.macro.value) != NULL)) { + dir4gridscripts = dmakeOdir_value->string_mb; + } + dir4gridscripts = Avo_PathNames::pathname_output_directory(dir4gridscripts); + hostName = Avo_PathNames::pathname_local_host(); + } + (void) sprintf(script_file, + NOCATGETS("%s/dmake.script.%s.%d.%d.XXXXXX"), + dir4gridscripts, + hostName, + getpid(), + file_number++); + } +#endif /* SGE_SUPPORT */ + process_running = run_rule_commands(local_host, commands); + + return build_running; +} + +/* + * doname_parallel(target, do_get, implicit) + * + * Processes the given target and finishes up any parallel + * processes left running. + * + * Return value: + * Result of target build + * + * Parameters: + * target Target to build + * do_get True if sccs get to be done + * implicit True if this is an implicit target + */ +Doname +doname_parallel(Name target, Boolean do_get, Boolean implicit) +{ + Doname result; + + result = doname_check(target, do_get, implicit, false); + if (result == build_ok || result == build_failed) { + return result; + } + finish_running(); + return (Doname) target->state; +} + +/* + * doname_subtree(target, do_get, implicit) + * + * Completely computes an object and its dependents for a + * serial subtree build. + * + * Parameters: + * target Target to build + * do_get True if sccs get to be done + * implicit True if this is an implicit target + * + * Static variables used: + * running_tail Tail of the list of running processes + * + * Global variables used: + * running_list The list of running processes + */ +static void +doname_subtree(Name target, Boolean do_get, Boolean implicit) +{ + Running save_running_list; + Running *save_running_tail; + + save_running_list = running_list; + save_running_tail = running_tail; + running_list = NULL; + running_tail = &running_list; + target->state = build_subtree; + target->checking_subtree = true; + while(doname_check(target, do_get, implicit, false) == build_running) { + target->checking_subtree = false; + finish_running(); + target->state = build_subtree; + } + target->checking_subtree = false; + running_list = save_running_list; + running_tail = save_running_tail; +} + +/* + * finish_running() + * + * Keeps processing until the running_list is emptied out. + * + * Parameters: + * + * Global variables used: + * running_list The list of running processes + */ +void +finish_running(void) +{ + while (running_list != NULL) { +#ifdef DISTRIBUTED + if (dmake_mode_type == distributed_mode) { + if ((just_did_subtree) || + (parallel_process_cnt == 0)) { + just_did_subtree = false; + } else { + (void) await_dist(false); + finish_children(true); + } + } else +#endif + { + await_parallel(false); + finish_children(true); + } + if (running_list != NULL) { + process_next(); + } + } +} + +/* + * process_next() + * + * Searches the running list for any targets which can start processing. + * This can be a pending target, a serial target, or a subtree target. + * + * Parameters: + * + * Static variables used: + * running_tail The end of the list of running procs + * subtree_conflict A target which conflicts with a subtree + * subtree_conflict2 The other target which conflicts + * + * Global variables used: + * commands_done True if commands executed + * debug_level Controls debug output + * parallel_process_cnt Number of parallel process running + * recursion_level Indentation for debug output + * running_list List of running processes + */ +static void +process_next(void) +{ + Running rp; + Running *rp_prev; + Property line; + Chain target_group; + Dependency dep; + Boolean quiescent = true; + Running *subtree_target; + Boolean saved_commands_done; + Property *conditionals; + + subtree_target = NULL; + subtree_conflict = NULL; + subtree_conflict2 = NULL; + /* + * If nothing currently running, build a serial target, if any. + */ +start_loop_1: + for (rp_prev = &running_list, rp = running_list; + rp != NULL && parallel_process_cnt == 0; + rp = rp->next) { + if (rp->state == build_serial) { + *rp_prev = rp->next; + if (rp->next == NULL) { + running_tail = rp_prev; + } + recursion_level = rp->recursion_level; + rp->target->state = build_pending; + (void) doname_check(rp->target, + rp->do_get, + rp->implicit, + false); + quiescent = false; + delete_running_struct(rp); + goto start_loop_1; + } else { + rp_prev = &rp->next; + } + } + /* + * Find a target to build. The target must be pending, have all + * its dependencies built, and not be in a target group with a target + * currently building. + */ +start_loop_2: + for (rp_prev = &running_list, rp = running_list; + rp != NULL; + rp = rp->next) { + if (!(rp->state == build_pending || + rp->state == build_subtree)) { + quiescent = false; + rp_prev = &rp->next; + } else if (rp->state == build_pending) { + line = get_prop(rp->target->prop, line_prop); + for (dep = line->body.line.dependencies; + dep != NULL; + dep = dep->next) { + if (dep->name->state == build_running || + dep->name->state == build_pending || + dep->name->state == build_serial) { + break; + } + } + if (dep == NULL) { + for (target_group = line->body.line.target_group; + target_group != NULL; + target_group = target_group->next) { + if (is_running(target_group->name)) { + break; + } + } + if (target_group == NULL) { + *rp_prev = rp->next; + if (rp->next == NULL) { + running_tail = rp_prev; + } + recursion_level = rp->recursion_level; + rp->target->state = rp->redo ? + build_dont_know : build_pending; + saved_commands_done = commands_done; + conditionals = + set_conditionals + (rp->conditional_cnt, + rp->conditional_targets); + rp->target->dont_activate_cond_values = true; + if ((doname_check(rp->target, + rp->do_get, + rp->implicit, + rp->target->has_target_prop ? true : false) != + build_running) && + !commands_done) { + commands_done = + saved_commands_done; + } + rp->target->dont_activate_cond_values = false; + reset_conditionals + (rp->conditional_cnt, + rp->conditional_targets, + conditionals); + quiescent = false; + delete_running_struct(rp); + goto start_loop_2; + } else { + rp_prev = &rp->next; + } + } else { + rp_prev = &rp->next; + } + } else { + rp_prev = &rp->next; + } + } + /* + * If nothing has been found to build and there exists a subtree + * target with no dependency conflicts, build it. + */ + if (quiescent) { +start_loop_3: + for (rp_prev = &running_list, rp = running_list; + rp != NULL; + rp = rp->next) { + if (rp->state == build_subtree) { + if (!dependency_conflict(rp->target)) { + *rp_prev = rp->next; + if (rp->next == NULL) { + running_tail = rp_prev; + } + recursion_level = rp->recursion_level; + doname_subtree(rp->target, + rp->do_get, + rp->implicit); +#ifdef DISTRIBUTED + just_did_subtree = true; +#endif + quiescent = false; + delete_running_struct(rp); + goto start_loop_3; + } else { + subtree_target = rp_prev; + rp_prev = &rp->next; + } + } else { + rp_prev = &rp->next; + } + } + } + /* + * If still nothing found to build, we either have a deadlock + * or a subtree with a dependency conflict with something waiting + * to build. + */ + if (quiescent) { + if (subtree_target == NULL) { + fatal(catgets(catd, 1, 126, "Internal error: deadlock detected in process_next")); + } else { + rp = *subtree_target; + if (debug_level > 0) { + warning(catgets(catd, 1, 127, "Conditional macro conflict encountered for %s between %s and %s"), + subtree_conflict2->string_mb, + rp->target->string_mb, + subtree_conflict->string_mb); + } + *subtree_target = (*subtree_target)->next; + if (rp->next == NULL) { + running_tail = subtree_target; + } + recursion_level = rp->recursion_level; + doname_subtree(rp->target, rp->do_get, rp->implicit); +#ifdef DISTRIBUTED + just_did_subtree = true; +#endif + delete_running_struct(rp); + } + } +} + +/* + * set_conditionals(cnt, targets) + * + * Sets the conditional macros for the targets given in the array of + * targets. The old macro values are returned in an array of + * Properties for later resetting. + * + * Return value: + * Array of conditional macro settings + * + * Parameters: + * cnt Number of targets + * targets Array of targets + */ +static Property * +set_conditionals(int cnt, Name *targets) +{ + Property *locals, *lp; + Name *tp; + + locals = (Property *) getmem(cnt * sizeof(Property)); + for (lp = locals, tp = targets; + cnt > 0; + cnt--, lp++, tp++) { + *lp = (Property) getmem((*tp)->conditional_cnt * + sizeof(struct _Property)); + set_locals(*tp, *lp); + } + return locals; +} + +/* + * reset_conditionals(cnt, targets, locals) + * + * Resets the conditional macros as saved in the given array of + * Properties. The resets are done in reverse order. Afterwards the + * data structures are freed. + * + * Parameters: + * cnt Number of targets + * targets Array of targets + * locals Array of dependency macro settings + */ +static void +reset_conditionals(int cnt, Name *targets, Property *locals) +{ + Name *tp; + Property *lp; + + for (tp = targets + (cnt - 1), lp = locals + (cnt - 1); + cnt > 0; + cnt--, tp--, lp--) { + reset_locals(*tp, + *lp, + get_prop((*tp)->prop, conditional_prop), + 0); + retmem_mb((caddr_t) *lp); + } + retmem_mb((caddr_t) locals); +} + +/* + * dependency_conflict(target) + * + * Returns true if there is an intersection between + * the subtree of the target and any dependents of the pending targets. + * + * Return value: + * True if conflict found + * + * Parameters: + * target Subtree target to check + * + * Static variables used: + * subtree_conflict Target conflict found + * subtree_conflict2 Second conflict found + * + * Global variables used: + * running_list List of running processes + * wait_name .WAIT, not a real dependency + */ +static Boolean +dependency_conflict(Name target) +{ + Property line; + Property pending_line; + Dependency dp; + Dependency pending_dp; + Running rp; + + /* Return if we are already checking this target */ + if (target->checking_subtree) { + return false; + } + target->checking_subtree = true; + line = get_prop(target->prop, line_prop); + if (line == NULL) { + target->checking_subtree = false; + return false; + } + /* Check each dependency of the target for conflicts */ + for (dp = line->body.line.dependencies; dp != NULL; dp = dp->next) { + /* Ignore .WAIT dependency */ + if (dp->name == wait_name) { + continue; + } + /* + * For each pending target, look for a dependency which + * is the same as a dependency of the subtree target. Since + * we can't build the subtree until all pending targets have + * finished which depend on the same dependency, this is + * a conflict. + */ + for (rp = running_list; rp != NULL; rp = rp->next) { + if (rp->state == build_pending) { + pending_line = get_prop(rp->target->prop, + line_prop); + if (pending_line == NULL) { + continue; + } + for(pending_dp = pending_line-> + body.line.dependencies; + pending_dp != NULL; + pending_dp = pending_dp->next) { + if (dp->name == pending_dp->name) { + target->checking_subtree + = false; + subtree_conflict = rp->target; + subtree_conflict2 = dp->name; + return true; + } + } + } + } + if (dependency_conflict(dp->name)) { + target->checking_subtree = false; + return true; + } + } + target->checking_subtree = false; + return false; +} + +/* + * await_parallel(waitflg) + * + * Waits for parallel children to exit and finishes their processing. + * If waitflg is false, the function returns after update_delay. + * + * Parameters: + * waitflg dwight + */ +void +await_parallel(Boolean waitflg) +{ +#ifdef _CHECK_UPDATE_H + static int number_of_unknown_children = 0; +#endif /* _CHECK_UPDATE_H */ + Boolean nohang; + pid_t pid; + int status; + Running rp; + int waiterr; + + nohang = false; + for ( ; ; ) { + if (!nohang) { + (void) alarm((int) update_delay); + } + pid = waitpid((pid_t)-1, + &status, + nohang ? WNOHANG : 0); + waiterr = errno; + if (!nohang) { + (void) alarm(0); + } + if (pid <= 0) { + if (waiterr == EINTR) { + if (waitflg) { + continue; + } else { + return; + } + } else { + return; + } + } + for (rp = running_list; + (rp != NULL) && (rp->pid != pid); + rp = rp->next) { + ; + } + if (rp == NULL) { +#ifdef _CHECK_UPDATE_H + /* Ignore first child - it is check_update */ + if (number_of_unknown_children <= 0) { + number_of_unknown_children = 1; + return; + } +#endif /* _CHECK_UPDATE_H */ + if (send_mtool_msgs) { + continue; + } else { + fatal(catgets(catd, 1, 128, "Internal error: returned child pid not in running_list")); + } + } else { + rp->state = (WIFEXITED(status) && WEXITSTATUS(status) == 0) ? build_ok : build_failed; + } + nohang = true; + parallel_process_cnt--; + +#if defined (TEAMWARE_MAKE_CMN) && defined (MAXJOBS_ADJUST_RFE4694000) + if (job_adjust_mode == ADJUST_M2) { + if (m2_release_job()) { + job_adjust_error(); + } + } +#endif + } +} + +/* + * finish_children(docheck) + * + * Finishes the processing for all targets which were running + * and have now completed. + * + * Parameters: + * docheck Completely check the finished target + * + * Static variables used: + * running_tail The tail of the running list + * + * Global variables used: + * continue_after_error -k flag + * fatal_in_progress True if we are finishing up after fatal err + * running_list List of running processes + */ +void +finish_children(Boolean docheck) +{ + int cmds_length; + Property line; + Property line2; + struct stat out_buf; + Running rp; + Running *rp_prev; + Cmd_line rule; + Boolean silent_flag; + + for (rp_prev = &running_list, rp = running_list; + rp != NULL; + rp = rp->next) { +bypass_for_loop_inc_4: + /* + * If the state is ok or failed, then this target has + * finished building. + * In parallel_mode, output the accumulated stdout/stderr. + * Read the auto dependency stuff, handle a failed build, + * update the target, then finish the doname process for + * that target. + */ + if (rp->state == build_ok || rp->state == build_failed) { + *rp_prev = rp->next; + if (rp->next == NULL) { + running_tail = rp_prev; + } + if ((line2 = rp->command) == NULL) { + line2 = get_prop(rp->target->prop, line_prop); + } + if (dmake_mode_type == distributed_mode) { + if (rp->make_refd) { + maybe_reread_make_state(); + } + } else { + /* + * Send an Avo_MToolJobResultMsg to maketool. + */ +#ifdef DISTRIBUTED + if (send_mtool_msgs) { + send_job_result_msg(rp); + } +#endif + /* + * Check if there were any job output + * from the parallel build. + */ + if (rp->stdout_file != NULL) { + if (stat(rp->stdout_file, &out_buf) < 0) { + fatal(catgets(catd, 1, 130, "stat of %s failed: %s"), + rp->stdout_file, + errmsg(errno)); + } + if ((line2 != NULL) && + (out_buf.st_size > 0)) { + cmds_length = 0; + for (rule = line2->body.line.command_used, + silent_flag = silent; + rule != NULL; + rule = rule->next) { + cmds_length += rule->command_line->hash.length + 1; + silent_flag = BOOLEAN(silent_flag || rule->silent); + } + if (out_buf.st_size != cmds_length || silent_flag || + output_mode == txt2_mode) { + dump_out_file(rp->stdout_file, false); + } + } + (void) unlink(rp->stdout_file); + retmem_mb(rp->stdout_file); + rp->stdout_file = NULL; + } +#if defined(REDIRECT_ERR) + if (!out_err_same && (rp->stderr_file != NULL)) { + if (stat(rp->stderr_file, &out_buf) < 0) { + fatal(catgets(catd, 1, 130, "stat of %s failed: %s"), + rp->stderr_file, + errmsg(errno)); + } + if ((line2 != NULL) && + (out_buf.st_size > 0)) { + dump_out_file(rp->stderr_file, true); + } + (void) unlink(rp->stderr_file); + retmem_mb(rp->stderr_file); + rp->stderr_file = NULL; + } +#endif + } + check_state(rp->temp_file); + if (rp->temp_file != NULL) { + free_name(rp->temp_file); + } + rp->temp_file = NULL; + if (rp->state == build_failed) { + line = get_prop(rp->target->prop, line_prop); + if (line != NULL) { + line->body.line.command_used = NULL; + } + if (continue_after_error || + fatal_in_progress || + !docheck) { + warning(catgets(catd, 1, 256, "Command failed for target `%s'"), + rp->command ? line2->body.line.target->string_mb : rp->target->string_mb); + build_failed_seen = true; + } else { + /* + * XXX??? - DMake needs to exit(), + * but shouldn't call fatal(). + */ +#ifdef PRINT_EXIT_STATUS + warning(NOCATGETS("I'm in finish_children. rp->state == build_failed.")); +#endif + + fatal(catgets(catd, 1, 258, "Command failed for target `%s'"), + rp->command ? line2->body.line.target->string_mb : rp->target->string_mb); + } + } + if (!docheck) { + delete_running_struct(rp); + rp = *rp_prev; + if (rp == NULL) { + break; + } else { + goto bypass_for_loop_inc_4; + } + } + update_target(get_prop(rp->target->prop, line_prop), + rp->state); + finish_doname(rp); + delete_running_struct(rp); + rp = *rp_prev; + if (rp == NULL) { + break; + } else { + goto bypass_for_loop_inc_4; + } + } else { + rp_prev = &rp->next; + } + } +} + +/* + * dump_out_file(filename, err) + * + * Write the contents of the file to stdout, then unlink the file. + * + * Parameters: + * filename Name of temp file containing output + * + * Global variables used: + */ +static void +dump_out_file(char *filename, Boolean err) +{ + int chars_read; + char copybuf[BUFSIZ]; + int fd; + int out_fd = (err ? 2 : 1); + + if ((fd = open(filename, O_RDONLY)) < 0) { + fatal(catgets(catd, 1, 141, "open failed for output file %s: %s"), + filename, + errmsg(errno)); + } + if (!silent && output_mode != txt2_mode) { + (void) fprintf(err ? stderr : stdout, + err ? + catgets(catd, 1, 338, "%s --> Job errors\n") : + catgets(catd, 1, 259, "%s --> Job output\n"), + local_host); + (void) fflush(err ? stderr : stdout); + } + for (chars_read = read(fd, copybuf, BUFSIZ); + chars_read > 0; + chars_read = read(fd, copybuf, BUFSIZ)) { + /* + * Read buffers from the source file until end or error. + */ + if (write(out_fd, copybuf, chars_read) < 0) { + fatal(catgets(catd, 1, 260, "write failed for output file %s: %s"), + filename, + errmsg(errno)); + } + } + (void) close(fd); + (void) unlink(filename); +} + +/* + * finish_doname(rp) + * + * Completes the processing for a target which was left running. + * + * Parameters: + * rp Running list entry for target + * + * Global variables used: + * debug_level Debug flag + * recursion_level Indentation for debug output + */ +static void +finish_doname(Running rp) +{ + int auto_count = rp->auto_count; + Name *automatics = rp->automatics; + Doname result = rp->state; + Name target = rp->target; + Name true_target = rp->true_target; + Property *conditionals; + + recursion_level = rp->recursion_level; + if (result == build_ok) { + if (true_target == NULL) { + (void) printf(NOCATGETS("Target = %s\n"), target->string_mb); + (void) printf(NOCATGETS(" State = %d\n"), result); + fatal(NOCATGETS("Internal error: NULL true_target in finish_doname")); + } + /* If all went OK, set a nice timestamp */ + if (true_target->stat.time == file_doesnt_exist) { + true_target->stat.time = file_max_time; + } + } + target->state = result; + if (target->is_member) { + Property member; + + /* Propagate the timestamp from the member file to the member */ + if ((target->stat.time != file_max_time) && + ((member = get_prop(target->prop, member_prop)) != NULL) && + (exists(member->body.member.member) > file_doesnt_exist)) { + target->stat.time = +/* + exists(member->body.member.member); + */ + member->body.member.member->stat.time; + } + } + /* + * Check if we found any new auto dependencies when we + * built the target. + */ + if ((result == build_ok) && check_auto_dependencies(target, + auto_count, + automatics)) { + if (debug_level > 0) { + (void) printf(catgets(catd, 1, 261, "%*sTarget `%s' acquired new dependencies from build, checking all dependencies\n"), + recursion_level, + "", + true_target->string_mb); + } + target->rechecking_target = true; + target->state = build_running; + + /* [tolik, Tue Mar 25 1997] + * Fix for bug 4038824: + * command line options set by conditional macros get dropped + * rp->conditional_cnt and rp->conditional_targets must be copied + * to new 'rp' during add_pending(). Set_conditionals() stores + * rp->conditional_targets to the global variable 'conditional_targets' + * Add_pending() will use this variable to set up 'rp'. + */ + conditionals = set_conditionals(rp->conditional_cnt, rp->conditional_targets); + add_pending(target, + recursion_level, + rp->do_get, + rp->implicit, + true); + reset_conditionals(rp->conditional_cnt, rp->conditional_targets, conditionals); + } +} + +/* + * new_running_struct() + * + * Constructor for Running struct. Creates a structure and initializes + * its fields. + * + */ +static Running new_running_struct() +{ + Running rp; + + rp = ALLOC(Running); + rp->target = NULL; + rp->true_target = NULL; + rp->command = NULL; + rp->sprodep_value = NULL; + rp->sprodep_env = NULL; + rp->auto_count = 0; + rp->automatics = NULL; + rp->pid = -1; + rp->job_msg_id = -1; + rp->stdout_file = NULL; + rp->stderr_file = NULL; + rp->temp_file = NULL; + rp->next = NULL; + return rp; +} + +/* + * add_running(target, true_target, command, recursion_level, auto_count, + * automatics, do_get, implicit) + * + * Adds a record on the running list for this target, which + * was just spawned and is running. + * + * Parameters: + * target Target being built + * true_target True target for target + * command Running command. + * recursion_level Debug indentation level + * auto_count Count of automatic dependencies + * automatics List of automatic dependencies + * do_get Sccs get flag + * implicit Implicit flag + * + * Static variables used: + * running_tail Tail of running list + * process_running PID of process + * + * Global variables used: + * current_line Current line for target + * current_target Current target being built + * stderr_file Temporary file for stdout + * stdout_file Temporary file for stdout + * temp_file_name Temporary file for auto dependencies + */ +void +add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit) +{ + Running rp; + Name *p; + + rp = new_running_struct(); + rp->state = build_running; + rp->target = target; + rp->true_target = true_target; + rp->command = command; + Property spro_val = get_prop(sunpro_dependencies->prop, macro_prop); + if(spro_val) { + rp->sprodep_value = spro_val->body.macro.value; + spro_val->body.macro.value = NULL; + spro_val = get_prop(sunpro_dependencies->prop, env_mem_prop); + if(spro_val) { + rp->sprodep_env = spro_val->body.env_mem.value; + spro_val->body.env_mem.value = NULL; + } + } + rp->recursion_level = recursion_level; + rp->do_get = do_get; + rp->implicit = implicit; + rp->auto_count = auto_count; + if (auto_count > 0) { + rp->automatics = (Name *) getmem(auto_count * sizeof (Name)); + for (p = rp->automatics; auto_count > 0; auto_count--) { + *p++ = *automatics++; + } + } else { + rp->automatics = NULL; + } +#ifdef DISTRIBUTED + if (dmake_mode_type == distributed_mode) { + rp->make_refd = called_make; + called_make = false; + } else +#endif + { + rp->pid = process_running; + process_running = -1; + childPid = -1; + } + rp->job_msg_id = job_msg_id; + rp->stdout_file = stdout_file; + rp->stderr_file = stderr_file; + rp->temp_file = temp_file_name; + rp->redo = false; + rp->next = NULL; + store_conditionals(rp); + stdout_file = NULL; + stderr_file = NULL; + temp_file_name = NULL; + current_target = NULL; + current_line = NULL; + *running_tail = rp; + running_tail = &rp->next; +} + +/* + * add_pending(target, recursion_level, do_get, implicit, redo) + * + * Adds a record on the running list for a pending target + * (waiting for its dependents to finish running). + * + * Parameters: + * target Target being built + * recursion_level Debug indentation level + * do_get Sccs get flag + * implicit Implicit flag + * redo True if this target is being redone + * + * Static variables used: + * running_tail Tail of running list + */ +void +add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo) +{ + Running rp; + rp = new_running_struct(); + rp->state = build_pending; + rp->target = target; + rp->recursion_level = recursion_level; + rp->do_get = do_get; + rp->implicit = implicit; + rp->redo = redo; + store_conditionals(rp); + *running_tail = rp; + running_tail = &rp->next; +} + +/* + * add_serial(target, recursion_level, do_get, implicit) + * + * Adds a record on the running list for a target which must be + * executed in serial after others have finished. + * + * Parameters: + * target Target being built + * recursion_level Debug indentation level + * do_get Sccs get flag + * implicit Implicit flag + * + * Static variables used: + * running_tail Tail of running list + */ +void +add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit) +{ + Running rp; + + rp = new_running_struct(); + rp->target = target; + rp->recursion_level = recursion_level; + rp->do_get = do_get; + rp->implicit = implicit; + rp->state = build_serial; + rp->redo = false; + store_conditionals(rp); + *running_tail = rp; + running_tail = &rp->next; +} + +/* + * add_subtree(target, recursion_level, do_get, implicit) + * + * Adds a record on the running list for a target which must be + * executed in isolation after others have finished. + * + * Parameters: + * target Target being built + * recursion_level Debug indentation level + * do_get Sccs get flag + * implicit Implicit flag + * + * Static variables used: + * running_tail Tail of running list + */ +void +add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit) +{ + Running rp; + + rp = new_running_struct(); + rp->target = target; + rp->recursion_level = recursion_level; + rp->do_get = do_get; + rp->implicit = implicit; + rp->state = build_subtree; + rp->redo = false; + store_conditionals(rp); + *running_tail = rp; + running_tail = &rp->next; +} + +/* + * store_conditionals(rp) + * + * Creates an array of the currently active targets with conditional + * macros (found in the chain conditional_targets) and puts that + * array in the Running struct. + * + * Parameters: + * rp Running struct for storing chain + * + * Global variables used: + * conditional_targets Chain of current dynamic conditionals + */ +static void +store_conditionals(Running rp) +{ + int cnt; + Chain cond_name; + + if (conditional_targets == NULL) { + rp->conditional_cnt = 0; + rp->conditional_targets = NULL; + return; + } + cnt = 0; + for (cond_name = conditional_targets; + cond_name != NULL; + cond_name = cond_name->next) { + cnt++; + } + rp->conditional_cnt = cnt; + rp->conditional_targets = (Name *) getmem(cnt * sizeof(Name)); + for (cond_name = conditional_targets; + cond_name != NULL; + cond_name = cond_name->next) { + rp->conditional_targets[--cnt] = cond_name->name; + } +} + +/* + * parallel_ok(target, line_prop_must_exists) + * + * Returns true if the target can be run in parallel + * + * Return value: + * True if can run in parallel + * + * Parameters: + * target Target being tested + * + * Global variables used: + * all_parallel True if all targets default to parallel + * only_parallel True if no targets default to parallel + */ +Boolean +parallel_ok(Name target, Boolean line_prop_must_exists) +{ + Boolean assign; + Boolean make_refd; + Property line; + Cmd_line rule; + + assign = make_refd = false; + if (((line = get_prop(target->prop, line_prop)) == NULL) && + line_prop_must_exists) { + return false; + } + if (line != NULL) { + for (rule = line->body.line.command_used; + rule != NULL; + rule = rule->next) { + if (rule->assign) { + assign = true; + } else if (rule->make_refd) { + make_refd = true; + } + } + } + if (assign) { + return false; + } else if (target->parallel) { + return true; + } else if (target->no_parallel) { + return false; + } else if (all_parallel) { + return true; + } else if (only_parallel) { + return false; + } else if (make_refd) { + return false; + } else { + return true; + } +} + +/* + * is_running(target) + * + * Returns true if the target is running. + * + * Return value: + * True if target is running + * + * Parameters: + * target Target to check + * + * Global variables used: + * running_list List of running processes + */ +Boolean +is_running(Name target) +{ + Running rp; + + if (target->state != build_running) { + return false; + } + for (rp = running_list; + rp != NULL && target != rp->target; + rp = rp->next); + if (rp == NULL) { + return false; + } else { + return (rp->state == build_running) ? true : false; + } +} + +/* + * This function replaces the makesh binary. + */ + +#ifdef SGE_SUPPORT +#define DO_CHECK(f) if (f <= 0) { \ + fprintf(stderr, \ + catgets(catd, 1, 347, "Could not write to file: %s: %s\n"), \ + script_file, errmsg(errno)); \ + _exit(1); \ + } +#endif /* SGE_SUPPORT */ + +static pid_t +run_rule_commands(char *host, char **commands) +{ + Boolean always_exec; + Name command; + Boolean ignore; + int length; + Doname result; + Boolean silent_flag; +#ifdef SGE_SUPPORT + wchar_t *wcmd, *tmp_wcs_buffer = NULL; + char *cmd, *tmp_mbs_buffer = NULL; + FILE *scrfp; + Name shell = getvar(shell_name); +#else + wchar_t *tmp_wcs_buffer; +#endif /* SGE_SUPPORT */ + + childPid = fork(); + switch (childPid) { + case -1: /* Error */ + fatal(catgets(catd, 1, 337, "Could not fork child process for dmake job: %s"), + errmsg(errno)); + break; + case 0: /* Child */ + /* To control the processed targets list is not the child's business */ + running_list = NULL; +#if defined(REDIRECT_ERR) + if(out_err_same) { + redirect_io(stdout_file, (char*)NULL); + } else { + redirect_io(stdout_file, stderr_file); + } +#else + redirect_io(stdout_file, (char*)NULL); +#endif +#ifdef SGE_SUPPORT + if (grid) { + int fdes = mkstemp(script_file); + if ((fdes < 0) || (scrfp = fdopen(fdes, "w")) == NULL) { + fprintf(stderr, + catgets(catd, 1, 341, "Could not create file: %s: %s\n"), + script_file, errmsg(errno)); + _exit(1); + } + if (IS_EQUAL(shell->string_mb, "")) { + shell = shell_name; + } + } +#endif /* SGE_SUPPORT */ + for (commands = commands; + (*commands != (char *)NULL); + commands++) { + silent_flag = silent; + ignore = false; + always_exec = false; + while ((**commands == (int) at_char) || + (**commands == (int) hyphen_char) || + (**commands == (int) plus_char)) { + if (**commands == (int) at_char) { + silent_flag = true; + } + if (**commands == (int) hyphen_char) { + ignore = true; + } + if (**commands == (int) plus_char) { + always_exec = true; + } + (*commands)++; + } +#ifdef SGE_SUPPORT + if (grid) { + if ((length = strlen(*commands)) >= MAXPATHLEN / 2) { + wcmd = tmp_wcs_buffer = ALLOC_WC(length * 2 + 1); + (void) mbstowcs(tmp_wcs_buffer, *commands, length * 2 + 1); + } else { + MBSTOWCS(wcs_buffer, *commands); + wcmd = wcs_buffer; + cmd = mbs_buffer; + } + wchar_t *from = wcmd + wslen(wcmd); + wchar_t *to = from + (from - wcmd); + *to = (int) nul_char; + while (from > wcmd) { + *--to = *--from; + if (*from == (int) newline_char) { // newline symbols are already quoted + *--to = *--from; + } else if (wschr(char_semantics_char, *from)) { + *--to = (int) backslash_char; + } + } + if (length >= MAXPATHLEN*MB_LEN_MAX/2) { // sizeof(mbs_buffer) / 2 + cmd = tmp_mbs_buffer = getmem((length * MB_LEN_MAX * 2) + 1); + (void) wcstombs(tmp_mbs_buffer, to, (length * MB_LEN_MAX * 2) + 1); + } else { + WCSTOMBS(mbs_buffer, to); + cmd = mbs_buffer; + } + char *mbst, *mbend; + if ((length > 0) && + !silent_flag) { + for (mbst = cmd; (mbend = strstr(mbst, "\\\n")) != NULL; mbst = mbend + 2) { + *mbend = '\0'; + DO_CHECK(fprintf(scrfp, NOCATGETS("/usr/bin/printf '%%s\\n' %s\\\\\n"), mbst)); + *mbend = '\\'; + } + DO_CHECK(fprintf(scrfp, NOCATGETS("/usr/bin/printf '%%s\\n' %s\n"), mbst)); + } + if (!do_not_exec_rule || + !working_on_targets || + always_exec) { +#if defined(linux) + if (0 != strcmp(shell->string_mb, (char*)NOCATGETS("/bin/sh"))) { + DO_CHECK(fprintf(scrfp, NOCATGETS("%s -c %s\n"), shell->string_mb, cmd)); + } else +#endif + DO_CHECK(fprintf(scrfp, NOCATGETS("%s -ce %s\n"), shell->string_mb, cmd)); + DO_CHECK(fputs(NOCATGETS("__DMAKECMDEXITSTAT=$?\nif [ ${__DMAKECMDEXITSTAT} -ne 0 ]; then\n"), scrfp)); + if (ignore) { + DO_CHECK(fprintf(scrfp, NOCATGETS("\techo %s ${__DMAKECMDEXITSTAT} %s\n"), + catgets(catd, 1, 343, "\"*** Error code"), + catgets(catd, 1, 344, "(ignored)\""))); + } else { + DO_CHECK(fprintf(scrfp, NOCATGETS("\techo %s ${__DMAKECMDEXITSTAT}\n"), + catgets(catd, 1, 342, "\"*** Error code\""))); + } + if (silent_flag) { + DO_CHECK(fprintf(scrfp, NOCATGETS("\techo %s\n"), + catgets(catd, 1, 345, "The following command caused the error:"))); + for (mbst = cmd; (mbend = strstr(mbst, "\\\n")) != NULL; mbst = mbend + 2) { + *mbend = '\0'; + DO_CHECK(fprintf(scrfp, NOCATGETS("\t/usr/bin/printf '%%s\\n' %s\\\\\n"), mbst)); + *mbend = '\\'; + } + DO_CHECK(fprintf(scrfp, NOCATGETS("\t/usr/bin/printf '%%s\\n' %s\n"), mbst)); + } + if (!ignore) { + DO_CHECK(fputs(NOCATGETS("\texit ${__DMAKECMDEXITSTAT}\n"), scrfp)); + } + DO_CHECK(fputs(NOCATGETS("fi\n"), scrfp)); + } + if (tmp_wcs_buffer) { + retmem_mb(tmp_mbs_buffer); + tmp_mbs_buffer = NULL; + } + if (tmp_wcs_buffer) { + retmem(tmp_wcs_buffer); + tmp_wcs_buffer = NULL; + } + continue; + } +#endif /* SGE_SUPPORT */ + if ((length = strlen(*commands)) >= MAXPATHLEN) { + tmp_wcs_buffer = ALLOC_WC(length + 1); + (void) mbstowcs(tmp_wcs_buffer, *commands, length + 1); + command = GETNAME(tmp_wcs_buffer, FIND_LENGTH); + retmem(tmp_wcs_buffer); + } else { + MBSTOWCS(wcs_buffer, *commands); + command = GETNAME(wcs_buffer, FIND_LENGTH); + } + if ((command->hash.length > 0) && + !silent_flag) { + (void) printf("%s\n", command->string_mb); + } + result = dosys(command, + ignore, + false, + false, /* bugs #4085164 & #4990057 */ + /* BOOLEAN(silent_flag && ignore), */ + always_exec, + (Name) NULL, + false); + if (result == build_failed) { + if (silent_flag) { + (void) printf(catgets(catd, 1, 152, "The following command caused the error:\n%s\n"), command->string_mb); + } + if (!ignore) { + _exit(1); + } + } + } +#ifndef SGE_SUPPORT + _exit(0); +#else + if (!grid) { + _exit(0); + } + DO_CHECK(fputs(NOCATGETS("exit 0\n"), scrfp)); + if (fclose(scrfp) != 0) { + fprintf(stderr, + catgets(catd, 1, 346, "Could not close file: %s: %s\n"), + script_file, errmsg(errno)); + _exit(1); + } + { + +#define DEFAULT_QRSH_TRIES_NUMBER 1 +#define DEFAULT_QRSH_TIMEOUT 0 + + static char *sge_env_var = NULL; + static int qrsh_tries_number = DEFAULT_QRSH_TRIES_NUMBER; + static int qrsh_timeout = DEFAULT_QRSH_TIMEOUT; +#define SGE_DEBUG +#ifdef SGE_DEBUG + static Boolean do_not_remove = false; +#endif /* SGE_DEBUG */ + if (sge_env_var == NULL) { + sge_env_var = getenv(NOCATGETS("__SPRO_DMAKE_SGE_TRIES")); + if (sge_env_var != NULL) { + qrsh_tries_number = atoi(sge_env_var); + if (qrsh_tries_number < 1 || qrsh_tries_number > 9) { + qrsh_tries_number = DEFAULT_QRSH_TRIES_NUMBER; + } + } + sge_env_var = getenv(NOCATGETS("__SPRO_DMAKE_SGE_TIMEOUT")); + if (sge_env_var != NULL) { + qrsh_timeout = atoi(sge_env_var); + if (qrsh_timeout <= 0) { + qrsh_timeout = DEFAULT_QRSH_TIMEOUT; + } + } else { + sge_env_var = ""; + } +#ifdef SGE_DEBUG + sge_env_var = getenv(NOCATGETS("__SPRO_DMAKE_SGE_DEBUG")); + if (sge_env_var == NULL) { + sge_env_var = ""; + } + if (strstr(sge_env_var, NOCATGETS("noqrsh")) != NULL) + qrsh_tries_number = 0; + if (strstr(sge_env_var, NOCATGETS("donotremove")) != NULL) + do_not_remove = true; +#endif /* SGE_DEBUG */ + } + for (int i = qrsh_tries_number; ; i--) + if ((childPid = fork()) < 0) { + fatal(catgets(catd, 1, 348, "Could not fork child process for qrsh job: %s"), + errmsg(errno)); + _exit(1); + } else if (childPid == 0) { + enable_interrupt((void (*) (int))SIG_DFL); + if (i > 0) { + static char qrsh_cmd[50+MAXPATHLEN] = NOCATGETS("qrsh -cwd -V -noshell -nostdin /bin/sh "); + static char *fname_ptr = NULL; + static char *argv[] = { NOCATGETS("sh"), + NOCATGETS("-fce"), + qrsh_cmd, + NULL}; + if (fname_ptr == NULL) { + fname_ptr = qrsh_cmd + strlen(qrsh_cmd); + } + strcpy(fname_ptr, script_file); + (void) execve(NOCATGETS("/bin/sh"), argv, environ); + } else { + static char *argv[] = { NOCATGETS("sh"), + script_file, + NULL}; + (void) execve(NOCATGETS("/bin/sh"), argv, environ); + } + fprintf(stderr, + catgets(catd, 1, 349, "Could not load `qrsh': %s\n"), + errmsg(errno)); + _exit(1); + } else { +#if defined (HP_UX) || defined (linux) || defined (SUN5_0) + int status; +#else + union wait status; +#endif + pid_t pid; + while ((pid = wait(&status)) != childPid) { + if (pid == -1) { + fprintf(stderr, + catgets(catd, 1, 350, "wait() failed: %s\n"), + errmsg(errno)); + _exit(1); + } + } + if (status != 0 && i > 0) { + if (i > 1) { + sleep(qrsh_timeout); + } + continue; + } +#ifdef SGE_DEBUG + if (do_not_remove) { + if (status) { + fprintf(stderr, + NOCATGETS("SGE script failed: %s\n"), + script_file); + } + _exit(status ? 1 : 0); + } +#endif /* SGE_DEBUG */ + (void) unlink(script_file); + _exit(status ? 1 : 0); + } + } +#endif /* SGE_SUPPORT */ + break; + default: + break; + } + return childPid; +} + +static void +maybe_reread_make_state(void) +{ + /* Copying dosys()... */ + if (report_dependencies_level == 0) { + make_state->stat.time = file_no_time; + (void) exists(make_state); + if (make_state_before == make_state->stat.time) { + return; + } + makefile_type = reading_statefile; + if (read_trace_level > 1) { + trace_reader = true; + } + temp_file_number++; + (void) read_simple_file(make_state, + false, + false, + false, + false, + false, + true); + trace_reader = false; + } +} + +#ifdef DISTRIBUTED +/* + * Create and send an Avo_MToolJobResultMsg. + */ +static void +send_job_result_msg(Running rp) +{ + Avo_MToolJobResultMsg *msg; + RWCollectable *xdr_msg; + + msg = new Avo_MToolJobResultMsg(); + msg->setResult(rp->job_msg_id, + (rp->state == build_ok) ? 0 : 1, + DONE); + append_job_result_msg(msg, + rp->stdout_file, + rp->stderr_file); + + xdr_msg = (RWCollectable *)msg; + xdr(get_xdrs_ptr(), xdr_msg); + (void) fflush(get_mtool_msgs_fp()); + + delete msg; +} + +/* + * Append the stdout/err to Avo_MToolJobResultMsg. + */ +static void +append_job_result_msg(Avo_MToolJobResultMsg *msg, char *outFn, char *errFn) +{ + FILE *fp; + char line[MAXPATHLEN]; + + fp = fopen(outFn, "r"); + if (fp == NULL) { + /* Hmmm... what should we do here? */ + return; + } + while (fgets(line, MAXPATHLEN, fp) != NULL) { + if (line[strlen(line) - 1] == '\n') { + line[strlen(line) - 1] = '\0'; + } + msg->appendOutput(AVO_STRDUP(line)); + } + (void) fclose(fp); +} +#endif + +static void +delete_running_struct(Running rp) +{ + if ((rp->conditional_cnt > 0) && + (rp->conditional_targets != NULL)) { + retmem_mb((char *) rp->conditional_targets); + } +/**/ + if ((rp->auto_count > 0) && + (rp->automatics != NULL)) { + retmem_mb((char *) rp->automatics); + } +/**/ + if(rp->sprodep_value) { + free_name(rp->sprodep_value); + } + if(rp->sprodep_env) { + retmem_mb(rp->sprodep_env); + } + retmem_mb((char *) rp); + +} + +#endif + diff --git a/usr/src/make_src/Make/bin/make/common/pmake.cc b/usr/src/make_src/Make/bin/make/common/pmake.cc new file mode 100644 index 0000000..3544077 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/pmake.cc @@ -0,0 +1,434 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)pmake.cc 1.9 06/12/12 + */ + +#pragma ident "@(#)pmake.cc 1.9 06/12/12" + +#ifdef TEAMWARE_MAKE_CMN + +/* + * Included files + */ +#include <arpa/inet.h> +#include <mk/defs.h> +#include <mksh/misc.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/utsname.h> +#include <rpc/rpc.h> /* host2netname(), netname2host() */ +#ifdef linux +# include <unistd.h> /* getdomainname() */ +#endif + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +/* + * File table of contents + */ +static int get_max(wchar_t **ms_address, wchar_t *hostname); +static Boolean pskip_comment(wchar_t **cp_address); +static void pskip_till_next_word(wchar_t **cp); +static Boolean pskip_white_space(wchar_t **cp_address); + + +/* + * read_make_machines(Name make_machines_name) + * + * For backwards compatibility w/ PMake 1.x, when DMake 2.x is + * being run in parallel mode, DMake should parse the PMake startup + * file $(HOME)/.make.machines to get the PMake max jobs. + * + * Return value: + * int of PMake max jobs + * + * Parameters: + * make_machines_name Name of .make.machines file + * + */ +int +read_make_machines(Name make_machines_name) +{ + wchar_t c; + Boolean default_make_machines; + struct hostent *hp; + wchar_t local_host[MAX_HOSTNAMELEN + 1]; + char local_host_mb[MAX_HOSTNAMELEN + 1] = ""; + int local_host_wslen; + wchar_t full_host[MAXNETNAMELEN + 1]; + int full_host_wslen = 0; + char *homedir; + Name MAKE_MACHINES; + struct stat make_machines_buf; + FILE *make_machines_file; + wchar_t *make_machines_list = NULL; + char *make_machines_list_mb = NULL; + wchar_t make_machines_path[MAXPATHLEN]; + char mb_make_machines_path[MAXPATHLEN]; + wchar_t *mp; + wchar_t *ms; + int pmake_max_jobs = 0; + struct utsname uts_info; + + + MBSTOWCS(wcs_buffer, NOCATGETS("MAKE_MACHINES")); + MAKE_MACHINES = GETNAME(wcs_buffer, FIND_LENGTH); + /* Did the user specify a .make.machines file on the command line? */ + default_make_machines = false; + if (make_machines_name == NULL) { + /* Try reading the default .make.machines file, in $(HOME). */ + homedir = getenv(NOCATGETS("HOME")); + if ((homedir != NULL) && (strlen(homedir) < (sizeof(mb_make_machines_path) - 16))) { + sprintf(mb_make_machines_path, + NOCATGETS("%s/.make.machines"), homedir); + MBSTOWCS(make_machines_path, mb_make_machines_path); + make_machines_name = GETNAME(make_machines_path, FIND_LENGTH); + default_make_machines = true; + } + if (make_machines_name == NULL) { + /* + * No $(HOME)/.make.machines file. + * Return 0 for PMake max jobs. + */ + return(0); + } + } +/* + make_machines_list_mb = getenv(MAKE_MACHINES->string_mb); + */ + /* Open the .make.machines file. */ + if ((make_machines_file = fopen(make_machines_name->string_mb, "r")) == NULL) { + if (!default_make_machines) { + /* Error opening .make.machines file. */ + fatal(catgets(catd, 1, 314, "Open of %s failed: %s"), + make_machines_name->string_mb, + errmsg(errno)); + } else { + /* + * No $(HOME)/.make.machines file. + * Return 0 for PMake max jobs. + */ + return(0); + } + /* Stat the .make.machines file to get the size of the file. */ + } else if (fstat(fileno(make_machines_file), &make_machines_buf) < 0) { + /* Error stat'ing .make.machines file. */ + fatal(catgets(catd, 1, 315, "Stat of %s failed: %s"), + make_machines_name->string_mb, + errmsg(errno)); + } else { + /* Allocate memory for "MAKE_MACHINES=<contents of .m.m>" */ + make_machines_list_mb = + (char *) getmem((int) (strlen(MAKE_MACHINES->string_mb) + + 2 + + make_machines_buf.st_size)); + sprintf(make_machines_list_mb, + "%s=", + MAKE_MACHINES->string_mb); + /* Read in the .make.machines file. */ + if (fread(make_machines_list_mb + strlen(MAKE_MACHINES->string_mb) + 1, + sizeof(char), + (int) make_machines_buf.st_size, + make_machines_file) != make_machines_buf.st_size) { + /* + * Error reading .make.machines file. + * Return 0 for PMake max jobs. + */ + warning(catgets(catd, 1, 316, "Unable to read %s"), + make_machines_name->string_mb); + (void) fclose(make_machines_file); + retmem_mb((caddr_t) make_machines_list_mb); + return(0); + } else { + (void) fclose(make_machines_file); + /* putenv "MAKE_MACHINES=<contents of .m.m>" */ + *(make_machines_list_mb + + strlen(MAKE_MACHINES->string_mb) + + 1 + + make_machines_buf.st_size) = (int) nul_char; + if (putenv(make_machines_list_mb) != 0) { + warning(catgets(catd, 1, 317, "Couldn't put contents of %s in environment"), + make_machines_name->string_mb); + } else { + make_machines_list_mb += strlen(MAKE_MACHINES->string_mb) + 1; + make_machines_list = ALLOC_WC(strlen(make_machines_list_mb) + 1); + (void) mbstowcs(make_machines_list, + make_machines_list_mb, + (strlen(make_machines_list_mb) + 1)); + } + } + } + + uname(&uts_info); + strcpy(local_host_mb, &uts_info.nodename[0]); + MBSTOWCS(local_host, local_host_mb); + local_host_wslen = wslen(local_host); + + // There is no getdomainname() function on Solaris. + // And netname2host() function does not work on Linux. + // So we have to use different APIs. +#ifdef linux + if (getdomainname(mbs_buffer, MAXNETNAMELEN+1) == 0) { + sprintf(mbs_buffer2, "%s.%s", local_host_mb, mbs_buffer); +#else + if (host2netname(mbs_buffer, NULL, NULL) && + netname2host(mbs_buffer, mbs_buffer2, MAXNETNAMELEN+1)) { +#endif + MBSTOWCS(full_host, mbs_buffer2); + full_host_wslen = wslen(full_host); + } + + for (ms = make_machines_list; + (ms) && (*ms ); + ) { + /* + * Skip white space and comments till you reach + * a machine name. + */ + pskip_till_next_word(&ms); + + /* + * If we haven't reached the end of file, process the + * machine name. + */ + if (*ms) { + /* + * If invalid machine name decrement counter + * and skip line. + */ + mp = ms; + SKIPWORD(ms); + c = *ms; + *ms++ = '\0'; /* Append null to machine name. */ + /* + * If this was the beginning of a comment + * (we overwrote a # sign) and it's not + * end of line yet, shift the # sign. + */ + if ((c == '#') && (*ms != '\n') && (*ms)) { + *ms = '#'; + } + WCSTOMBS(mbs_buffer, mp); + /* + * Print "Ignoring unknown host" if: + * 1) hostname is longer than MAX_HOSTNAMELEN, or + * 2) hostname is unknown + */ + if ((wslen(mp) > MAX_HOSTNAMELEN) || + ((hp = gethostbyname(mbs_buffer)) == NULL)) { + warning(catgets(catd, 1, 318, "Ignoring unknown host %s"), + mbs_buffer); + SKIPTOEND(ms); + /* Increment ptr if not end of file. */ + if (*ms) { + ms++; + } + } else { + /* Compare current hostname with local_host. */ + if (wslen(mp) == local_host_wslen && + IS_WEQUALN(mp, local_host, local_host_wslen)) { + /* + * Bingo, local_host is in .make.machines. + * Continue reading. + */ + pmake_max_jobs = PMAKE_DEF_MAX_JOBS; + /* Compare current hostname with full_host. */ + } else if (wslen(mp) == full_host_wslen && + IS_WEQUALN(mp, full_host, full_host_wslen)) { + /* + * Bingo, full_host is in .make.machines. + * Continue reading. + */ + pmake_max_jobs = PMAKE_DEF_MAX_JOBS; + } else { + if (c != '\n') { + SKIPTOEND(ms); + if (*ms) { + ms++; + } + } + continue; + } + /* If we get here, local_host is in .make.machines. */ + if (c != '\n') { + /* Now look for keyword 'max'. */ + MBSTOWCS(wcs_buffer, NOCATGETS("max")); + SKIPSPACE(ms); + while ((*ms != '\n') && (*ms)) { + if (*ms == '#') { + pskip_comment(&ms); + } else if (IS_WEQUALN(ms, wcs_buffer, 3)) { + /* Skip "max". */ + ms += 3; + pmake_max_jobs = get_max(&ms, mp); + SKIPSPACE(ms); + } else { + warning(catgets(catd, 1, 322, "unknown option for host %s"), mbs_buffer); + SKIPTOEND(ms); + break; + } + } + } + break; /* out of outermost for() loop. */ + } + } + } + retmem(make_machines_list); + return(pmake_max_jobs); +} + +/* + * pskip_till_next_word(cp) + * + * Parameters: + * cp the address of the string pointer. + * + * On return: + * cp points to beginning of machine name. + * + */ +static void +pskip_till_next_word(wchar_t **cp) +{ + /* + * Keep recursing until all combinations of white spaces + * and comments have been skipped. + */ + if (pskip_white_space(cp) || pskip_comment(cp)) { + pskip_till_next_word(cp); + } +} + +/* + * pskip_white_space(cp_address) + * + * Advances the string pointer so that it points to the first + * non white character (space/tab/linefeed). + * + * Parameters: + * cp_address the address of the string pointer. + * + * Return Value: + * True if the pointer was changed. + * + */ +static Boolean +pskip_white_space(wchar_t **cp_address) +{ + wchar_t *cp = *cp_address; + + while (*cp && iswspace(*cp)) { + cp++; + } + /* Have we skipped any characters? */ + if (cp != *cp_address) { + *cp_address = cp; + return(true); + } else { + return(false); + } +} + +/* + * pskip_comment(cp_address) + * + * If cp_address is pointing to '#' (the beginning of a comment), + * increment the pointer till you reach end of line. + * + * Parameters: + * cp_address the address of the string pointer. + * + * Return Value: + * True if the pointer was changed. + * + */ +static Boolean +pskip_comment(wchar_t **cp_address) +{ + wchar_t *cp = *cp_address; + + /* Is this the beginning of a comment? Skip till end of line. */ + if (*cp == '#') { + SKIPTOEND(cp); + } + /* Have we skipped a comment line? */ + if (cp != *cp_address) { + *cp_address = cp; + return(true); + } else { + return(false); + } +} + +static int +get_max(wchar_t **ms_address, wchar_t *hostname) +{ + wchar_t *ms = *ms_address; + int limit = PMAKE_DEF_MAX_JOBS; /* Default setting. */ + + WCSTOMBS(mbs_buffer, hostname); + /* Look for `='. */ + SKIPSPACE(ms); + if ((!*ms) || (*ms == '\n') || (*ms != '=')) { + SKIPTOEND(ms); + warning(catgets(catd, 1, 319, "expected `=' after max, ignoring rest of line for host %s"), + mbs_buffer); + *ms_address = ms; + return((int) limit); + } else { + ms++; + SKIPSPACE(ms); + if ((*ms != '\n') && (*ms != '\0')) { + /* We've found, hopefully, a valid "max" value. */ + limit = (int) wcstol(ms, &ms, 10); + if (limit < 1) { + limit = PMAKE_DEF_MAX_JOBS; + warning(catgets(catd, 1, 320, "max value cannot be less than or equal to zero for host %s"), mbs_buffer); + } + } else { + /* No "max" value after "max=". */ + warning(catgets(catd, 1, 321, "no max value specified for host %s"), mbs_buffer); + } + *ms_address = ms; + return(limit); + } +} + +#endif + diff --git a/usr/src/make_src/Make/bin/make/common/read.cc b/usr/src/make_src/Make/bin/make/common/read.cc new file mode 100644 index 0000000..586d609 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/read.cc @@ -0,0 +1,2197 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)read.cc 1.64 06/12/12 + */ + +#pragma ident "@(#)read.cc 1.64 06/12/12" + +/* + * read.c + * + * This file contains the makefile reader. + */ + +/* + * Included files + */ +#include <avo/avo_alloca.h> /* alloca() */ +#include <errno.h> /* errno */ +#include <fcntl.h> /* fcntl() */ +#include <mk/defs.h> +#include <mksh/macro.h> /* expand_value(), expand_macro() */ +#include <mksh/misc.h> /* getmem() */ +#include <mksh/read.h> /* get_next_block_fn() */ +#include <sys/uio.h> /* read() */ +#include <unistd.h> /* read(), unlink() */ + +#if defined(HP_UX) || defined(linux) +#include <avo/types.h> +extern "C" Avo_err *avo_find_run_dir(char **dirp); +#endif + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +static int line_started_with_space=0; // Used to diagnose spaces instead of tabs + +/* + * File table of contents + */ +static void parse_makefile(register Name true_makefile_name, register Source source); +static Source push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source); +extern void enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen); +extern Name normalize_name(register wchar_t *name_string, register int length); + +/* + * read_simple_file(makefile_name, chase_path, doname_it, + * complain, must_exist, report_file, lock_makefile) + * + * Make the makefile and setup to read it. Actually read it if it is stdio + * + * Return value: + * false if the read failed + * + * Parameters: + * makefile_name Name of the file to read + * chase_path Use the makefile path when opening file + * doname_it Call doname() to build the file first + * complain Print message if doname/open fails + * must_exist Generate fatal if file is missing + * report_file Report file when running -P + * lock_makefile Lock the makefile when reading + * + * Static variables used: + * + * Global variables used: + * do_not_exec_rule Is -n on? + * file_being_read Set to the name of the new file + * line_number The number of the current makefile line + * makefiles_used A list of all makefiles used, appended to + */ + + +Boolean +read_simple_file(register Name makefile_name, register Boolean chase_path, register Boolean doname_it, Boolean complain, Boolean must_exist, Boolean report_file, Boolean lock_makefile) +{ + static short max_include_depth; + register Property makefile = maybe_append_prop(makefile_name, + makefile_prop); + Boolean forget_after_parse = false; + static pathpt makefile_path; + register int n; + char *path; + register Source source = ALLOC(Source); + Property orig_makefile = makefile; + Dependency *dpp; + Dependency dp; + register int length; + wchar_t *previous_file_being_read = file_being_read; + int previous_line_number = line_number; + wchar_t previous_current_makefile[MAXPATHLEN]; + Makefile_type save_makefile_type; + Name normalized_makefile_name; + register wchar_t *string_start; + register wchar_t *string_end; + + +#if defined(HP_UX) || defined(linux) + Avo_err *findrundir_err; + char *run_dir, makerules_dir[BUFSIZ]; +#endif + + wchar_t * wcb = get_wstring(makefile_name->string_mb); + +#ifdef NSE + if (report_file){ + wscpy(previous_current_makefile, current_makefile); + wscpy(current_makefile, wcb); + } +#endif + if (max_include_depth++ >= 40) { + fatal(catgets(catd, 1, 66, "Too many nested include statements")); + } + if (makefile->body.makefile.contents != NULL) { + retmem(makefile->body.makefile.contents); + } + source->inp_buf = + source->inp_buf_ptr = + source->inp_buf_end = NULL; + source->error_converting = false; + makefile->body.makefile.contents = NULL; + makefile->body.makefile.size = 0; + if ((makefile_name->hash.length != 1) || + (wcb[0] != (int) hyphen_char)) { + if ((makefile->body.makefile.contents == NULL) && + (doname_it)) { + if (makefile_path == NULL) { + add_dir_to_path(".", + &makefile_path, + -1); +#ifdef SUN5_0 + add_dir_to_path(NOCATGETS("/usr/share/lib/make"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/etc/default"), + &makefile_path, + -1); +#elif defined(HP_UX) + findrundir_err = avo_find_run_dir(&run_dir); + if (! findrundir_err) { + (void) sprintf(makerules_dir, NOCATGETS("%s/../share/lib/make"), run_dir); + add_dir_to_path(makerules_dir, + &makefile_path, + -1); + } + + add_dir_to_path(NOCATGETS("/opt/SUNWspro/share/lib/make"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/usr/share/lib/make"), + &makefile_path, + -1); +#elif defined(linux) + findrundir_err = avo_find_run_dir(&run_dir); + if (! findrundir_err) { + (void) sprintf(makerules_dir, NOCATGETS("%s/../lib"), run_dir); + add_dir_to_path(makerules_dir, + &makefile_path, + -1); + } + + add_dir_to_path(NOCATGETS("/usr/SUNWspro/lib"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/opt/SUNWspro/share/lib/make"), + &makefile_path, + -1); + add_dir_to_path(NOCATGETS("/usr/share/lib/make"), + &makefile_path, + -1); +#else + add_dir_to_path(NOCATGETS("/usr/include/make"), + &makefile_path, + -1); +#endif + } + save_makefile_type = makefile_type; + makefile_type = reading_nothing; + if (doname(makefile_name, true, false) == build_dont_know) { + /* Try normalized filename */ + string_start=get_wstring(makefile_name->string_mb); + for (string_end=string_start+1; *string_end != NULL; string_end++); + normalized_makefile_name=normalize_name(string_start, string_end - string_start); + if ((strcmp(makefile_name->string_mb, normalized_makefile_name->string_mb) == 0) || + (doname(normalized_makefile_name, true, false) == build_dont_know)) { + n = access_vroot(makefile_name->string_mb, + 4, + chase_path ? + makefile_path : NULL, + VROOT_DEFAULT); + if (n == 0) { + get_vroot_path((char **) NULL, + &path, + (char **) NULL); + if ((path[0] == (int) period_char) && + (path[1] == (int) slash_char)) { + path += 2; + } + MBSTOWCS(wcs_buffer, path); + makefile_name = GETNAME(wcs_buffer, + FIND_LENGTH); + } + } + retmem(string_start); + /* + * Commented out: retmem_mb(normalized_makefile_name->string_mb); + * We have to return this memory, but it seems to trigger a bug + * in dmake or in Sun C++ 5.7 compiler (it works ok if this code + * is compiled using Sun C++ 5.6). + */ + // retmem_mb(normalized_makefile_name->string_mb); + } + makefile_type = save_makefile_type; + } + source->string.free_after_use = false; + source->previous = NULL; + source->already_expanded = false; + /* Lock the file for read, but not when -n. */ + if (lock_makefile && + !do_not_exec_rule) { + + make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(NOCATGETS(".lock")) + 1); + (void) sprintf(make_state_lockfile, + NOCATGETS("%s.lock"), + make_state->string_mb); + (void) file_lock(make_state->string_mb, + make_state_lockfile, + (int *) &make_state_locked, + 0); + if(!make_state_locked) { + printf(NOCATGETS("-- NO LOCKING for read\n")); + retmem_mb(make_state_lockfile); + make_state_lockfile = 0; + return failed; + } + } + if (makefile->body.makefile.contents == NULL) { + save_makefile_type = makefile_type; + makefile_type = reading_nothing; + if ((doname_it) && + (doname(makefile_name, true, false) == build_failed)) { + if (complain) { + (void) fprintf(stderr, +#ifdef DISTRIBUTED + catgets(catd, 1, 67, "dmake: Couldn't dmake `%s'\n"), +#else + catgets(catd, 1, 237, "make: Couldn't make `%s'\n"), +#endif + makefile_name->string_mb); + } + max_include_depth--; + makefile_type = save_makefile_type; + return failed; + } + makefile_type = save_makefile_type; + // + // Before calling exists() make sure that we have the right timestamp + // + makefile_name->stat.time = file_no_time; + + if (exists(makefile_name) == file_doesnt_exist) { + if (complain || + (makefile_name->stat.stat_errno != ENOENT)) { + if (must_exist) { + fatal(catgets(catd, 1, 68, "Can't find `%s': %s"), + makefile_name->string_mb, + errmsg(makefile_name-> + stat.stat_errno)); + } else { + warning(catgets(catd, 1, 69, "Can't find `%s': %s"), + makefile_name->string_mb, + errmsg(makefile_name-> + stat.stat_errno)); + } + } + max_include_depth--; + if(make_state_locked && (make_state_lockfile != NULL)) { + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } + retmem(wcb); + retmem_mb((char *)source); + return failed; + } + /* + * These values are the size and bytes of + * the MULTI-BYTE makefile. + */ + orig_makefile->body.makefile.size = + makefile->body.makefile.size = + source->bytes_left_in_file = + makefile_name->stat.size; + if (report_file) { + for (dpp = &makefiles_used; + *dpp != NULL; + dpp = &(*dpp)->next); + dp = ALLOC(Dependency); + dp->next = NULL; + dp->name = makefile_name; + dp->automatic = false; + dp->stale = false; + dp->built = false; + *dpp = dp; + } + source->fd = open_vroot(makefile_name->string_mb, + O_RDONLY, + 0, + NULL, + VROOT_DEFAULT); + if (source->fd < 0) { + if (complain || (errno != ENOENT)) { + if (must_exist) { + fatal(catgets(catd, 1, 70, "Can't open `%s': %s"), + makefile_name->string_mb, + errmsg(errno)); + } else { + warning(catgets(catd, 1, 71, "Can't open `%s': %s"), + makefile_name->string_mb, + errmsg(errno)); + } + } + max_include_depth--; + return failed; + } + (void) fcntl(source->fd, F_SETFD, 1); + orig_makefile->body.makefile.contents = + makefile->body.makefile.contents = + source->string.text.p = + source->string.buffer.start = + ALLOC_WC((int) (makefile_name->stat.size + 2)); + if (makefile_type == reading_cpp_file) { + forget_after_parse = true; + } + source->string.text.end = source->string.text.p; + source->string.buffer.end = + source->string.text.p + makefile_name->stat.size; + } else { + /* Do we ever reach here? */ + source->fd = -1; + source->string.text.p = + source->string.buffer.start = + makefile->body.makefile.contents; + source->string.text.end = + source->string.buffer.end = + source->string.text.p + makefile->body.makefile.size; + source->bytes_left_in_file = + makefile->body.makefile.size; + } + file_being_read = wcb; + } else { + char *stdin_text_p; + char *stdin_text_end; + char *stdin_buffer_start; + char *stdin_buffer_end; + char *p_mb; + int num_mb_chars; + size_t num_wc_chars; + + MBSTOWCS(wcs_buffer, NOCATGETS("Standard in")); + makefile_name = GETNAME(wcs_buffer, FIND_LENGTH); + /* + * Memory to read standard in, then convert it + * to wide char strings. + */ + stdin_buffer_start = + stdin_text_p = getmem(length = 1024); + stdin_buffer_end = stdin_text_p + length; + MBSTOWCS(wcs_buffer, NOCATGETS("standard input")); + file_being_read = (wchar_t *) wsdup(wcs_buffer); + line_number = 0; + while ((n = read(fileno(stdin), + stdin_text_p, + length)) > 0) { + length -= n; + stdin_text_p += n; + if (length == 0) { + p_mb = getmem(length = 1024 + + (stdin_buffer_end - + stdin_buffer_start)); + (void) strncpy(p_mb, + stdin_buffer_start, + (stdin_buffer_end - + stdin_buffer_start)); + retmem_mb(stdin_buffer_start); + stdin_text_p = p_mb + + (stdin_buffer_end - stdin_buffer_start); + stdin_buffer_start = p_mb; + stdin_buffer_end = + stdin_buffer_start + length; + length = 1024; + } + } + if (n < 0) { + fatal(catgets(catd, 1, 72, "Error reading standard input: %s"), + errmsg(errno)); + } + stdin_text_p = stdin_buffer_start; + stdin_text_end = stdin_buffer_end - length; + num_mb_chars = stdin_text_end - stdin_text_p; + + /* + * Now, convert the sequence of multibyte chars into + * a sequence of corresponding wide character codes. + */ + source->string.free_after_use = false; + source->previous = NULL; + source->bytes_left_in_file = 0; + source->fd = -1; + source->already_expanded = false; + source->string.buffer.start = + source->string.text.p = ALLOC_WC(num_mb_chars + 1); + source->string.buffer.end = + source->string.text.p + num_mb_chars; + num_wc_chars = mbstowcs(source->string.text.p, + stdin_text_p, + num_mb_chars); + if ((int) num_wc_chars >= 0) { + source->string.text.end = + source->string.text.p + num_wc_chars; + } + (void) retmem_mb(stdin_text_p); + } + line_number = 1; + if (trace_reader) { + (void) printf(catgets(catd, 1, 73, ">>>>>>>>>>>>>>>> Reading makefile %s\n"), + makefile_name->string_mb); + } + parse_makefile(makefile_name, source); + if (trace_reader) { + (void) printf(catgets(catd, 1, 74, ">>>>>>>>>>>>>>>> End of makefile %s\n"), + makefile_name->string_mb); + } +#ifdef NSE + if (report_file && (previous_current_makefile[0] != NULL)) { + wscpy(current_makefile, previous_current_makefile); + } +#endif + if(file_being_read) { + retmem(file_being_read); + } + file_being_read = previous_file_being_read; + line_number = previous_line_number; + makefile_type = reading_nothing; + max_include_depth--; + if (make_state_locked) { + /* Unlock .make.state. */ + unlink(make_state_lockfile); + make_state_locked = false; + retmem_mb(make_state_lockfile); + } + if (forget_after_parse) { + retmem(makefile->body.makefile.contents); + makefile->body.makefile.contents = NULL; + } + retmem_mb((char *)source); + return succeeded; +} + +/* + * parse_makefile(true_makefile_name, source) + * + * Strings are read from Sources. + * When macros are found, their values are represented by a + * Source that is pushed on a stack. At end of string + * (that is returned from GET_CHAR() as 0), the block is popped. + * + * Parameters: + * true_makefile_name The name of makefile we are parsing + * source The source block to read from + * + * Global variables used: + * do_not_exec_rule Is -n on? + * line_number The number of the current makefile line + * makefile_type What kind of makefile are we reading? + * empty_name The Name "" + */ +static void +parse_makefile(register Name true_makefile_name, register Source source) +{ +/* + char mb_buffer[MB_LEN_MAX]; + */ + register wchar_t *source_p; + register wchar_t *source_end; + register wchar_t *string_start; + wchar_t *string_end; + register Boolean macro_seen_in_string; + Boolean append; + String_rec name_string; + wchar_t name_buffer[STRING_BUFFER_LENGTH]; + register int distance; + register int paren_count; + int brace_count; + int char_number; + Cmd_line command; + Cmd_line command_tail; + Name macro_value; + + Name_vector_rec target; + Name_vector_rec depes; + Name_vector_rec extra_name_vector; + Name_vector current_names; + Name_vector extra_names = &extra_name_vector; + Name_vector nvp; + Boolean target_group_seen; + + register Reader_state state; + register Reader_state on_eoln_state; + register Separator separator; + + wchar_t buffer[4 * STRING_BUFFER_LENGTH]; + Source extrap; + + Boolean save_do_not_exec_rule = do_not_exec_rule; + Name makefile_name; + + static Name sh_name; + static Name shell_name; + int i; + + static wchar_t include_space[10]; + static wchar_t include_tab[10]; + int tmp_bytes_left_in_string; + Boolean tmp_maybe_include = false; + int emptycount = 0; + Boolean first_target; + + String_rec include_name; + wchar_t include_buffer[STRING_BUFFER_LENGTH]; + + target.next = depes.next = NULL; + /* Move some values from their struct to register declared locals */ + CACHE_SOURCE(0); + + start_new_line: + /* + * Read whitespace on old line. Leave pointer on first char on + * next line. + */ + first_target = true; + on_eoln_state = exit_state; +/* + for (WCTOMB(mb_buffer, GET_CHAR()); + 1; + source_p++, WCTOMB(mb_buffer, GET_CHAR())) + switch (mb_buffer[0]) { + */ + for (char_number=0; 1; source_p++,char_number++) switch (GET_CHAR()) { + case nul_char: + /* End of this string. Pop it and return to the previous one */ + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case newline_char: + end_of_line: + source_p++; + if (source->fd >= 0) { + line_number++; + } + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + /* Go back to the top of this loop */ + goto start_new_line; + case newline_char: + case numbersign_char: + case dollar_char: + case space_char: + case tab_char: + /* + * Go back to the top of this loop since the + * new line does not start with a regular char. + */ + goto start_new_line; + default: + /* We found the first proper char on the new line */ + goto start_new_line_no_skip; + } + case space_char: + if (char_number == 0) + line_started_with_space=line_number; + case tab_char: + /* Whitespace. Just keep going in this loop */ + break; + case numbersign_char: + /* Comment. Skip over it */ + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + } + source_p--; + break; + case backslash_char: + /* Comments can be continued */ + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + source_p--; + break; + } + } + if(*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + /* + * After we skip the comment we go to + * the end of line handler since end of + * line terminates comments. + */ + goto end_of_line; + } + } + case dollar_char: + /* Macro reference */ + if (source->already_expanded) { + /* + * If we are reading from the expansion of a + * macro we already expanded everything enough. + */ + goto start_new_line_no_skip; + } + /* + * Expand the value and push the Source on the stack of + * things being read. + */ + source_p++; + UNCACHE_SOURCE(); + { + Source t = (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(1); + break; + default: + /* We found the first proper char on the new line */ + goto start_new_line_no_skip; + } + + /* + * We found the first normal char (one that starts an identifier) + * on the newline. + */ +start_new_line_no_skip: + /* Inspect that first char to see if it maybe is special anyway */ + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + goto start_new_line_no_skip; + case newline_char: + /* Just in case */ + goto start_new_line; + case exclam_char: + /* Evaluate the line before it is read */ + string_start = source_p + 1; + macro_seen_in_string = false; + /* Stuff the line in a string so we can eval it. */ + for (; 1; source_p++) { + switch (GET_CHAR()) { + case newline_char: + goto eoln_1; + case nul_char: + if (source->fd > 0) { + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK( + name_string, name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + break; + } + eoln_1: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + extrap = (Source) + alloca((int) sizeof (Source_rec)); + extrap->string.buffer.start = NULL; + extrap->inp_buf = + extrap->inp_buf_ptr = + extrap->inp_buf_end = NULL; + extrap->error_converting = false; + if (*source_p == (int) nul_char) { + source_p++; + } + /* Eval the macro */ + expand_value(GETNAME(name_string.buffer.start, + FIND_LENGTH), + &extrap->string, + false); + if (name_string.free_after_use) { + retmem(name_string.buffer.start); + } + UNCACHE_SOURCE(); + extrap->string.text.p = + extrap->string.buffer.start; + extrap->fd = -1; + /* And push the value */ + extrap->previous = source; + source = extrap; + CACHE_SOURCE(0); + goto line_evald; + } + } + default: + goto line_evald; + } + + /* We now have a line we can start reading */ + line_evald: + if (source == NULL) { + GOTO_STATE(exit_state); + } + /* Check if this is an include command */ + if ((makefile_type == reading_makefile) && + !source->already_expanded) { + if (include_space[0] == (int) nul_char) { + MBSTOWCS(include_space, NOCATGETS("include ")); + MBSTOWCS(include_tab, NOCATGETS("include\t")); + } + if ((IS_WEQUALN(source_p, include_space, 8)) || + (IS_WEQUALN(source_p, include_tab, 8))) { + source_p += 7; + if (iswspace(*source_p)) { + Makefile_type save_makefile_type; + wchar_t *name_start; + int name_length; + + /* + * Yes, this is an include. + * Skip spaces to get to the filename. + */ + while (iswspace(*source_p) || + (*source_p == (int) nul_char)) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + + default: + source_p++; + break; + } + } + + string_start = source_p; + /* Find the end of the filename */ + macro_seen_in_string = false; + while (!iswspace(*source_p) || + (*source_p == (int) nul_char)) { + switch (GET_CHAR()) { + case nul_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + GET_NEXT_BLOCK(source); + string_start = source_p; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + + default: + source_p++; + break; + } + } + + source->string.text.p = source_p; + if (macro_seen_in_string) { + append_string(string_start, + &name_string, + source_p - string_start); + name_start = name_string.buffer.start; + name_length = name_string.text.p - name_start; + } else { + name_start = string_start; + name_length = source_p - string_start; + } + + /* Strip "./" from the head of the name */ + if ((name_start[0] == (int) period_char) && + (name_start[1] == (int) slash_char)) { + name_start += 2; + name_length -= 2; + } + /* if include file name is surrounded by double quotes */ + if ((name_start[0] == (int) doublequote_char) && + (name_start[name_length - 1] == (int) doublequote_char)) { + name_start += 1; + name_length -= 2; + + /* if name does not begin with a slash char */ + if (name_start[0] != (int) slash_char) { + if ((name_start[0] == (int) period_char) && + (name_start[1] == (int) slash_char)) { + name_start += 2; + name_length -= 2; + } + + INIT_STRING_FROM_STACK(include_name, include_buffer); + APPEND_NAME(true_makefile_name, + &include_name, + true_makefile_name->hash.length); + + wchar_t *slash = wsrchr(include_name.buffer.start, (int) slash_char); + if (slash != NULL) { + include_name.text.p = slash + 1; + append_string(name_start, + &include_name, + name_length); + + name_start = include_name.buffer.start; + name_length = include_name.text.p - name_start; + } + } + } + + /* Even when we run -n we want to create makefiles */ + do_not_exec_rule = false; + makefile_name = GETNAME(name_start, name_length); + if (makefile_name->dollar) { + String_rec destination; + wchar_t buffer[STRING_BUFFER_LENGTH]; + wchar_t *p; + wchar_t *q; + + INIT_STRING_FROM_STACK(destination, buffer); + expand_value(makefile_name, + &destination, + false); + for (p = destination.buffer.start; + (*p != (int) nul_char) && iswspace(*p); + p++); + for (q = p; + (*q != (int) nul_char) && !iswspace(*q); + q++); + makefile_name = GETNAME(p, q-p); + if (destination.free_after_use) { + retmem(destination.buffer.start); + } + } + source_p++; + UNCACHE_SOURCE(); + /* Read the file */ + save_makefile_type = makefile_type; + if (read_simple_file(makefile_name, + true, + true, + true, + false, + true, + false) == failed) { + fatal_reader(catgets(catd, 1, 75, "Read of include file `%s' failed"), + makefile_name->string_mb); + } + makefile_type = save_makefile_type; + do_not_exec_rule = save_do_not_exec_rule; + CACHE_SOURCE(0); + goto start_new_line; + } else { + source_p -= 7; + } + } else { + /* Check if the word include was split across 8K boundary. */ + + tmp_bytes_left_in_string = source->string.text.end - source_p; + if (tmp_bytes_left_in_string < 8) { + tmp_maybe_include = false; + if (IS_WEQUALN(source_p, + include_space, + tmp_bytes_left_in_string)) { + tmp_maybe_include = true; + } + if (tmp_maybe_include) { + GET_NEXT_BLOCK(source); + tmp_maybe_include = false; + goto line_evald; + } + } + } + } + + /* Reset the status in preparation for the new line */ + for (nvp = ⌖ nvp != NULL; nvp = nvp->next) { + nvp->used = 0; + } + for (nvp = &depes; nvp != NULL; nvp = nvp->next) { + nvp->used = 0; + } + target_group_seen = false; + command = command_tail = NULL; + macro_value = NULL; + append = false; + current_names = ⌖ + SET_STATE(scan_name_state); + on_eoln_state = illegal_eoln_state; + separator = none_seen; + + /* The state machine starts here */ + enter_state: + while (1) switch (state) { + +/**************************************************************** + * Scan name state + */ +case scan_name_state: + /* Scan an identifier. We skip over chars until we find a break char */ + /* First skip white space. */ + for (; 1; source_p++) switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case newline_char: + /* We found the end of the line. */ + /* Do postprocessing or return error */ + source_p++; + if (source->fd >= 0) { + line_number++; + } + GOTO_STATE(on_eoln_state); + case backslash_char: + /* Continuation */ + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } else { + source_p--; + } + break; + case tab_char: + case space_char: + /* Whitespace is skipped */ + break; + case numbersign_char: + /* Comment. Skip over it */ + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + } + source_p--; + break; + case backslash_char: + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + source_p--; + break; + } + } + if(*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + source_p++; + if (source->fd >= 0) { + line_number++; + } + GOTO_STATE(on_eoln_state); + } + } + case dollar_char: + /* Macro reference. Expand and push value */ + if (source->already_expanded) { + goto scan_name; + } + source_p++; + UNCACHE_SOURCE(); + { + Source t = (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(1); + break; + default: + /* End of white space */ + goto scan_name; + } + + /* First proper identifier character */ + scan_name: + + string_start = source_p; + paren_count = brace_count = 0; + macro_seen_in_string = false; + resume_name_scan: + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + /* Save what we have seen so far of the identifier */ + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + /* Get more text to read */ + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case newline_char: + if (paren_count > 0) { + fatal_reader(catgets(catd, 1, 76, "Unmatched `(' on line")); + } + if (brace_count > 0) { + fatal_reader(catgets(catd, 1, 77, "Unmatched `{' on line")); + } + source_p++; + /* Enter name */ + current_names = enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p - 1, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) sizeof (Name_vector_rec)); + } + /* Do postprocessing or return error */ + if (source->fd >= 0) { + line_number++; + } + GOTO_STATE(on_eoln_state); + case backslash_char: + /* Check if this is a quoting backslash */ + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + macro_seen_in_string = true; + } + append_string(string_start, + &name_string, + source_p - string_start); + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + *source_p = (int) space_char; + string_start = source_p; + goto resume_name_scan; + } else { + string_start = source_p; + break; + } + break; + case numbersign_char: + if (paren_count + brace_count > 0) { + break; + } + fatal_reader(catgets(catd, 1, 78, "Unexpected comment seen")); + case dollar_char: + if (source->already_expanded) { + break; + } + /* Save the identifier so far */ + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + /* Eval and push the macro */ + source_p++; + UNCACHE_SOURCE(); + { + Source t = + (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(1); + string_start = source_p + 1; + break; + case parenleft_char: + paren_count++; + break; + case parenright_char: + if (--paren_count < 0) { + fatal_reader(catgets(catd, 1, 79, "Unmatched `)' on line")); + } + break; + case braceleft_char: + brace_count++; + break; + case braceright_char: + if (--brace_count < 0) { + fatal_reader(catgets(catd, 1, 80, "Unmatched `}' on line")); + } + break; + case ampersand_char: + case greater_char: + case bar_char: + if (paren_count + brace_count == 0) { + source_p++; + } + /* Fall into */ + case tab_char: + case space_char: + if (paren_count + brace_count > 0) { + break; + } + current_names = enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) sizeof (Name_vector_rec)); + } + goto enter_state; + case colon_char: + if (paren_count + brace_count > 0) { + break; + } + if (separator == conditional_seen) { + break; + } +/** POSIX **/ +#if 0 + if(posix) { + emptycount = 0; + } +#endif +/** END POSIX **/ + /* End of the target list. We now start reading */ + /* dependencies or a conditional assignment */ + if (separator != none_seen) { + fatal_reader(catgets(catd, 1, 81, "Extra `:', `::', or `:=' on dependency line")); + } + /* Enter the last target */ + if ((string_start != source_p) || + macro_seen_in_string) { + current_names = + enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) + sizeof (Name_vector_rec)); + } + } + /* Check if it is ":" "::" or ":=" */ + scan_colon_label: + switch (*++source_p) { + case nul_char: + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(enter_dependencies_state); + } + goto scan_colon_label; + case equal_char: + if(svr4) { + fatal_reader(catgets(catd, 1, 82, "syntax error")); + } + separator = conditional_seen; + source_p++; + current_names = &depes; + GOTO_STATE(scan_name_state); + case colon_char: + separator = two_colon; + source_p++; + break; + default: + separator = one_colon; + } + current_names = &depes; + on_eoln_state = enter_dependencies_state; + GOTO_STATE(scan_name_state); + case semicolon_char: + if (paren_count + brace_count > 0) { + break; + } + /* End of reading names. Start reading the rule */ + if ((separator != one_colon) && + (separator != two_colon)) { + fatal_reader(catgets(catd, 1, 83, "Unexpected command seen")); + } + /* Enter the last dependency */ + if ((string_start != source_p) || + macro_seen_in_string) { + current_names = + enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) + sizeof (Name_vector_rec)); + } + } + source_p++; + /* Make sure to enter a rule even if the is */ + /* no text here */ + command = command_tail = ALLOC(Cmd_line); + command->next = NULL; + command->command_line = empty_name; + command->make_refd = false; + command->ignore_command_dependency = false; + command->assign = false; + command->ignore_error = false; + command->silent = false; + + GOTO_STATE(scan_command_state); + case plus_char: + /* + ** following code drops the target separator plus char if it starts + ** a line. + */ + if(first_target && !macro_seen_in_string && + source_p == string_start) { + for (; 1; source_p++) + switch (GET_CHAR()) { + case nul_char: + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case plus_char: + source_p++; + while (*source_p == (int) nul_char) { + if (source_p != string_start) { + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + } + GET_NEXT_BLOCK(source); + string_start = source_p; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p == (int) tab_char || + *source_p == (int) space_char) { + macro_seen_in_string = false; + string_start = source_p + 1; + } else { + goto resume_name_scan; + } + break; + case tab_char: + case space_char: + string_start = source_p + 1; + break; + default: + goto resume_name_scan; + } + } + if (paren_count + brace_count > 0) { + break; + } + /* We found "+=" construct */ + if (source_p != string_start) { + /* "+" is not a break char. */ + /* Ignore it if it is part of an identifier */ + source_p++; + goto resume_name_scan; + } + /* Make sure the "+" is followed by a "=" */ + scan_append: + switch (*++source_p) { + case nul_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + source_p--; + string_start = source_p; + if (source == NULL) { + GOTO_STATE(illegal_eoln_state); + } + goto scan_append; + case equal_char: + if(!svr4) { + append = true; + } else { + fatal_reader(catgets(catd, 1, 84, "Must be a separator on rules")); + } + break; + default: + /* The "+" just starts a regular name. */ + /* Start reading that name */ + goto resume_name_scan; + } + /* Fall into */ + case equal_char: + if (paren_count + brace_count > 0) { + break; + } + /* We found macro assignment. */ + /* Check if it is legal and if it is appending */ + switch (separator) { + case none_seen: + separator = equal_seen; + on_eoln_state = enter_equal_state; + break; + case conditional_seen: + on_eoln_state = enter_conditional_state; + break; + default: + /* Reader must special check for "MACRO:sh=" */ + /* notation */ + if (sh_name == NULL) { + MBSTOWCS(wcs_buffer, NOCATGETS("sh")); + sh_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, NOCATGETS("shell")); + shell_name = GETNAME(wcs_buffer, FIND_LENGTH); + } + + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start + ); + + if ( (((target.used == 1) && + (depes.used == 1) && + (depes.names[0] == sh_name)) || + ((target.used == 1) && + (depes.used == 0) && + (separator == one_colon) && + (GETNAME(name_string.buffer.start,FIND_LENGTH) == sh_name))) && + (!svr4)) { + String_rec macro_name; + wchar_t buffer[100]; + + INIT_STRING_FROM_STACK(macro_name, + buffer); + APPEND_NAME(target.names[0], + ¯o_name, + FIND_LENGTH); + append_char((int) colon_char, + ¯o_name); + APPEND_NAME(sh_name, + ¯o_name, + FIND_LENGTH); + target.names[0] = + GETNAME(macro_name.buffer.start, + FIND_LENGTH); + separator = equal_seen; + on_eoln_state = enter_equal_state; + break; + } else if ( (((target.used == 1) && + (depes.used == 1) && + (depes.names[0] == shell_name)) || + ((target.used == 1) && + (depes.used == 0) && + (separator == one_colon) && + (GETNAME(name_string.buffer.start,FIND_LENGTH) == shell_name))) && + (!svr4)) { + String_rec macro_name; + wchar_t buffer[100]; + + INIT_STRING_FROM_STACK(macro_name, + buffer); + APPEND_NAME(target.names[0], + ¯o_name, + FIND_LENGTH); + append_char((int) colon_char, + ¯o_name); + APPEND_NAME(shell_name, + ¯o_name, + FIND_LENGTH); + target.names[0] = + GETNAME(macro_name.buffer.start, + FIND_LENGTH); + separator = equal_seen; + on_eoln_state = enter_equal_state; + break; + } + if(svr4) { + fatal_reader(catgets(catd, 1, 85, "syntax error")); + } + else { + fatal_reader(catgets(catd, 1, 86, "Macro assignment on dependency line")); + } + } + if (append) { + source_p--; + } + /* Enter the macro name */ + if ((string_start != source_p) || + macro_seen_in_string) { + current_names = + enter_name(&name_string, + macro_seen_in_string, + string_start, + source_p, + current_names, + &extra_names, + &target_group_seen); + first_target = false; + if (extra_names == NULL) { + extra_names = (Name_vector) + alloca((int) + sizeof (Name_vector_rec)); + } + } + if (append) { + source_p++; + } + macro_value = NULL; + source_p++; + distance = 0; + /* Skip whitespace to the start of the value */ + macro_seen_in_string = false; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case backslash_char: + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + if (*source_p != (int) newline_char) { + if (!macro_seen_in_string) { + macro_seen_in_string = + true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_char((int) + backslash_char, + &name_string); + append_char(*source_p, + &name_string); + string_start = source_p+1; + goto macro_value_start; + } else { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + case numbersign_char: + string_start = source_p; + goto macro_value_end; + case tab_char: + case space_char: + break; + default: + string_start = source_p; + goto macro_value_start; + } + } + macro_value_start: + /* Find the end of the value */ + for (; 1; source_p++) { + if (distance != 0) { + *source_p = *(source_p + distance); + } + switch (GET_CHAR()) { + case nul_char: + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + break; + case backslash_char: + source_p++; + if (distance != 0) { + *source_p = + *(source_p + distance); + } + if (*source_p == (int) nul_char) { + if (!macro_seen_in_string) { + macro_seen_in_string = + true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + +/* BID_1225561 */ + *(source_p - 1) = (int) space_char; + append_string(string_start, + &name_string, + source_p - + string_start - 1); + GET_NEXT_BLOCK(source); + string_start = source_p; + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (distance != 0) { + *source_p = + *(source_p + + distance); + } + if (*source_p == (int) newline_char) { + append_char((int) space_char, &name_string); + } else { + append_char((int) backslash_char, &name_string); + } +/****************/ + } + if (*source_p == (int) newline_char) { + source_p--; + line_number++; + distance++; + *source_p = (int) space_char; + while ((*(source_p + + distance + 1) == + (int) tab_char) || + (*(source_p + + distance + 1) == + (int) space_char)) { + distance++; + } + } + break; + case newline_char: + case numbersign_char: + goto macro_value_end; + } + } + macro_value_end: + /* Complete the value in the string */ + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + if (name_string.buffer.start != name_string.text.p) { + macro_value = + GETNAME(name_string.buffer.start, + FIND_LENGTH); + } + if (name_string.free_after_use) { + retmem(name_string.buffer.start); + } + for (; distance > 0; distance--) { + *source_p++ = (int) space_char; + } + GOTO_STATE(on_eoln_state); + } + } + +/**************************************************************** + * enter dependencies state + */ + case enter_dependencies_state: + enter_dependencies_label: +/* Expects pointer on first non whitespace char after last dependency. (On */ +/* next line.) We end up here after having read a "targets : dependencies" */ +/* line. The state checks if there is a rule to read and if so dispatches */ +/* to scan_command_state scan_command_state reads one rule line and the */ +/* returns here */ + + /* First check if the first char on the next line is special */ + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK(source); + if (source == NULL) { + break; + } + goto enter_dependencies_label; + case exclam_char: + /* The line should be evaluate before it is read */ + macro_seen_in_string = false; + string_start = source_p + 1; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case newline_char: + goto eoln_2; + case nul_char: + if (source->fd > 0) { + if (!macro_seen_in_string) { + macro_seen_in_string = true; + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + break; + } + eoln_2: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + extrap = (Source) + alloca((int) sizeof (Source_rec)); + extrap->string.buffer.start = NULL; + extrap->inp_buf = + extrap->inp_buf_ptr = + extrap->inp_buf_end = NULL; + extrap->error_converting = false; + expand_value(GETNAME(name_string.buffer.start, + FIND_LENGTH), + &extrap->string, + false); + if (name_string.free_after_use) { + retmem(name_string.buffer.start); + } + UNCACHE_SOURCE(); + extrap->string.text.p = + extrap->string.buffer.start; + extrap->fd = -1; + extrap->previous = source; + source = extrap; + CACHE_SOURCE(0); + goto enter_dependencies_label; + } + } + case dollar_char: + if (source->already_expanded) { + break; + } + source_p++; + UNCACHE_SOURCE(); + { + Source t = (Source) alloca((int) sizeof (Source_rec)); + source = push_macro_value(t, + buffer, + sizeof buffer, + source); + } + CACHE_SOURCE(0); + goto enter_dependencies_label; + case numbersign_char: + if (makefile_type != reading_makefile) { + source_p++; + GOTO_STATE(scan_command_state); + } + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + } + source_p--; + break; + case backslash_char: + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + if (source->error_converting) { + // Illegal byte sequence - skip its first byte + source->inp_buf_ptr++; + source_p--; + break; + } + } + if(*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + } + break; + case newline_char: + source_p++; + if (source->fd >= 0) { + line_number++; + } + goto enter_dependencies_label; + } + } + + case tab_char: + GOTO_STATE(scan_command_state); + } + + /* We read all the command lines for the target/dependency line. */ + /* Enter the stuff */ + enter_target_groups_and_dependencies( &target, &depes, command, + separator, target_group_seen); + + goto start_new_line; + +/**************************************************************** + * scan command state + */ +case scan_command_state: + /* We need to read one rule line. Do that and return to */ + /* the enter dependencies state */ + string_start = source_p; + macro_seen_in_string = false; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case backslash_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + string_start = source_p; + goto command_newline; + } + } + append_char((int) backslash_char, &name_string); + append_char(*source_p, &name_string); + if (*source_p == (int) newline_char) { + if (source->fd >= 0) { + line_number++; + } + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + string_start = source_p; + goto command_newline; + } + } + if (*source_p == (int) tab_char) { + source_p++; + } + } else { + if (*++source_p == (int) nul_char) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + string_start = source_p; + goto command_newline; + } + } + } + string_start = source_p; + if ((*source_p == (int) newline_char) || + (*source_p == (int) backslash_char) || + (*source_p == (int) nul_char)) { + source_p--; + } + break; + case newline_char: + command_newline: + if ((string_start != source_p) || + macro_seen_in_string) { + if (macro_seen_in_string) { + append_string(string_start, + &name_string, + source_p - string_start); + string_start = + name_string.buffer.start; + string_end = name_string.text.p; + } else { + string_end = source_p; + } + while ((*string_start != (int) newline_char) && + iswspace(*string_start)){ + string_start++; + } + if ((string_end > string_start) || + (makefile_type == reading_statefile)) { + if (command_tail == NULL) { + command = + command_tail = + ALLOC(Cmd_line); + } else { + command_tail->next = + ALLOC(Cmd_line); + command_tail = + command_tail->next; + } + command_tail->next = NULL; + command_tail->make_refd = false; + command_tail->ignore_command_dependency = false; + command_tail->assign = false; + command_tail->ignore_error = false; + command_tail->silent = false; + command_tail->command_line = + GETNAME(string_start, + string_end - string_start); + if (macro_seen_in_string && + name_string.free_after_use) { + retmem(name_string. + buffer.start); + } + } + } + do { + if ((source != NULL) && (source->fd >= 0)) { + line_number++; + } + if ((source != NULL) && + (*++source_p == (int) nul_char)) { + GET_NEXT_BLOCK(source); + if (source == NULL) { + GOTO_STATE(on_eoln_state); + } + } + } while (*source_p == (int) newline_char); + + GOTO_STATE(enter_dependencies_state); + case nul_char: + if (!macro_seen_in_string) { + INIT_STRING_FROM_STACK(name_string, + name_buffer); + } + append_string(string_start, + &name_string, + source_p - string_start); + macro_seen_in_string = true; + GET_NEXT_BLOCK(source); + string_start = source_p; + source_p--; + if (source == NULL) { + GOTO_STATE(enter_dependencies_state); + } + break; + } + } + +/**************************************************************** + * enter equal state + */ +case enter_equal_state: + if (target.used != 1) { + GOTO_STATE(poorly_formed_macro_state); + } + enter_equal(target.names[0], macro_value, append); + goto start_new_line; + +/**************************************************************** + * enter conditional state + */ +case enter_conditional_state: + if (depes.used != 1) { + GOTO_STATE(poorly_formed_macro_state); + } + for (nvp = ⌖ nvp != NULL; nvp = nvp->next) { + for (i = 0; i < nvp->used; i++) { + enter_conditional(nvp->names[i], + depes.names[0], + macro_value, + append); + } + } + goto start_new_line; + +/**************************************************************** + * Error states + */ +case illegal_bytes_state: + fatal_reader(catgets(catd, 1, 340, "Invalid byte sequence")); +case illegal_eoln_state: + if (line_number > 1) { + if (line_started_with_space == (line_number - 1)) { + line_number--; + fatal_reader(catgets(catd, 1, 90, "Unexpected end of line seen\n\t*** missing separator (did you mean TAB instead of 8 spaces?)")); + } + } + fatal_reader(catgets(catd, 1, 87, "Unexpected end of line seen")); +case poorly_formed_macro_state: + fatal_reader(catgets(catd, 1, 88, "Badly formed macro assignment")); +case exit_state: + return; +default: + fatal_reader(catgets(catd, 1, 89, "Internal error. Unknown reader state")); +} +} + +/* + * push_macro_value(bp, buffer, size, source) + * + * Macro and function that evaluates one macro + * and makes the reader read from the value of it + * + * Return value: + * The source block to read the macro from + * + * Parameters: + * bp The new source block to fill in + * buffer Buffer to read from + * size size of the buffer + * source The old source block + * + * Global variables used: + */ +static Source +push_macro_value(register Source bp, register wchar_t *buffer, int size, register Source source) +{ + bp->string.buffer.start = bp->string.text.p = buffer; + bp->string.text.end = NULL; + bp->string.buffer.end = buffer + (size/SIZEOFWCHAR_T); + bp->string.free_after_use = false; + bp->inp_buf = + bp->inp_buf_ptr = + bp->inp_buf_end = NULL; + bp->error_converting = false; + expand_macro(source, &bp->string, (wchar_t *) NULL, false); + bp->string.text.p = bp->string.buffer.start; + + /* 4209588: 'make' doesn't understand a macro with whitespaces in the head as target. + * strip whitespace from the begining of the macro value + */ + while (iswspace(*bp->string.text.p)) { + bp->string.text.p++; + } + + bp->fd = -1; + bp->already_expanded = true; + bp->previous = source; + return bp; +} + +/* + * enter_target_groups_and_dependencies(target, depes, command, separator, + * target_group_seen) + * + * Parameters: + * target Structure that shows the target(s) on the line + * we are currently parsing. This can looks like + * target1 .. targetN : dependencies + * commands + * or + * target1 + .. + targetN : dependencies + * commands + * depes Dependencies + * command Points to the command(s) to be executed for + * this target. + * separator : or :: or := + * target_group_seen Set if we have target1 + .. + targetN + * + * + * After reading the command lines for a target, this routine + * is called to setup the dependencies and the commands for it. + * If the target is a % pattern or part of a target group, then + * the appropriate routines are called. + */ + +void +enter_target_groups_and_dependencies(Name_vector target, Name_vector depes, Cmd_line command, Separator separator, Boolean target_group_seen) +{ + int i; + Boolean reset= true; + Chain target_group_member; + Percent percent_ptr; + + for (; target != NULL; target = target->next) { + for (i = 0; i < target->used; i++) { + if (target->names[i] != NULL) { + if (target_group_seen) { + target_group_member = + find_target_groups(target, i, reset); + if(target_group_member == NULL) { + fatal_reader(catgets(catd, 1, 328, "Unexpected '+' on dependency line")); + } + } + reset = false; + + /* If we saw it in the makefile it must be + * a file */ + target->names[i]->stat.is_file = true; + /* Make sure that we use dependencies + * entered for makefiles */ + target->names[i]->state = build_dont_know; + + /* If the target is special we delegate + * the processing */ + if (target->names[i]->special_reader + != no_special) { + special_reader(target->names[i], + depes, + command); + } + /* Check if this is a "a%b : x%y" type rule */ + else if (target->names[i]->percent) { + percent_ptr = + enter_percent(target->names[i], + target->target_group[i], + depes, command); + if (target_group_seen) { + target_group_member->percent_member = + percent_ptr; + } + } else if (target->names[i]->dollar) { + enter_dyntarget(target->names[i]); + enter_dependencies + (target->names[i], + target->target_group[i], + depes, + command, + separator); + } else { + if (target_group_seen) { + target_group_member->percent_member = + NULL; + } + + enter_dependencies + (target->names[i], + target->target_group[i], + depes, + command, + separator); + } + } + } + } +} + + diff --git a/usr/src/make_src/Make/bin/make/common/read2.cc b/usr/src/make_src/Make/bin/make/common/read2.cc new file mode 100644 index 0000000..e1a9e1f --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/read2.cc @@ -0,0 +1,1938 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)read2.cc 1.53 06/12/12 + */ + +#pragma ident "@(#)read2.cc 1.53 06/12/12" + +/* + * read.c + * + * This file contains the makefile reader. + */ + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/dosys.h> /* sh_command2string() */ +#include <mksh/macro.h> /* expand_value() */ +#include <mksh/misc.h> /* retmem() */ +#include <stdarg.h> /* va_list, va_start(), va_end() */ + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +static Boolean built_last_make_run_seen; + +/* + * File table of contents + */ +static Name_vector enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names); +extern Name normalize_name(register wchar_t *name_string, register int length); +static void read_suffixes_list(register Name_vector depes); +static void make_relative(wchar_t *to, wchar_t *result); +static void print_rule(register Cmd_line command); +static void sh_transform(Name *name, Name *value); + + +/* + * enter_name(string, tail_present, string_start, string_end, + * current_names, extra_names, target_group_seen) + * + * Take one string and enter it as a name. The string is passed in + * two parts. A make string and possibly a C string to append to it. + * The result is stuffed in the vector current_names. + * extra_names points to a vector that is used if current_names overflows. + * This is allocad in the calling routine. + * Here we handle the "lib.a[members]" notation. + * + * Return value: + * The name vector that was used + * + * Parameters: + * tail_present Indicates if both C and make string was passed + * string_start C string + * string_end Pointer to char after last in C string + * string make style string with head of name + * current_names Vector to deposit the name in + * extra_names Where to get next name vector if we run out + * target_group_seen Pointer to boolean that is set if "+" is seen + * + * Global variables used: + * makefile_type When we read a report file we normalize paths + * plus Points to the Name "+" + */ + +Name_vector +enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen) +{ + Name name; + register wchar_t *cp; + wchar_t ch; + + /* If we were passed a separate tail of the name we append it to the */ + /* make string with the rest of it */ + if (tail_present) { + append_string(string_start, string, string_end - string_start); + string_start = string->buffer.start; + string_end = string->text.p; + } + ch = *string_end; + *string_end = (int) nul_char; + /* + * Check if there are any ( or [ that are not prefixed with $. + * If there are, we have to deal with the lib.a(members) format. + */ + for (cp = (wchar_t *) wschr(string_start, (int) parenleft_char); + cp != NULL; + cp = (wchar_t *) wschr(cp + 1, (int) parenleft_char)) { + if (*(cp - 1) != (int) dollar_char) { + *string_end = ch; + return enter_member_name(string_start, + cp, + string_end, + current_names, + extra_names); + } + } + *string_end = ch; + + if (makefile_type == reading_cpp_file) { + /* Remove extra ../ constructs if we are reading from a report file */ + name = normalize_name(string_start, string_end - string_start); + } else { + /* + * /tolik, fix bug 1197477/ + * Normalize every target name before entering. + * ..//obj/a.o and ../obj//a.o are not two different targets. + * There is only one target ../obj/a.o + */ + /*name = GETNAME(string_start, string_end - string_start);*/ + name = normalize_name(string_start, string_end - string_start); + } + + /* Internalize the name. Detect the name "+" (target group here) */ +if(current_names->used != 0 && current_names->names[current_names->used-1] == plus) { + if(name == plus) { + return current_names; + } +} + /* If the current_names vector is full we patch in the one from */ + /* extra_names */ + if (current_names->used == VSIZEOF(current_names->names)) { + if (current_names->next != NULL) { + current_names = current_names->next; + } else { + current_names->next = *extra_names; + *extra_names = NULL; + current_names = current_names->next; + current_names->used = 0; + current_names->next = NULL; + } + } + current_names->target_group[current_names->used] = NULL; + current_names->names[current_names->used++] = name; + if (name == plus) { + *target_group_seen = true; + } + if (tail_present && string->free_after_use) { + retmem(string->buffer.start); + } + return current_names; +} + +/* + * enter_member_name(lib_start, member_start, string_end, + * current_names, extra_names) + * + * A string has been found to contain member names. + * (The "lib.a[members]" and "lib.a(members)" notation) + * Handle it pretty much as enter_name() does for simple names. + * + * Return value: + * The name vector that was used + * + * Parameters: + * lib_start Points to the of start of "lib.a(member.o)" + * member_start Points to "member.o" from above string. + * string_end Points to char after last of above string. + * current_names Vector to deposit the name in + * extra_names Where to get next name vector if we run out + * + * Global variables used: + */ +static Name_vector +enter_member_name(register wchar_t *lib_start, register wchar_t *member_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names) +{ + register Boolean entry = false; + wchar_t buffer[STRING_BUFFER_LENGTH]; + Name lib; + Name member; + Name name; + Property prop; + wchar_t *memberp; + wchar_t *q; + register int paren_count; + register Boolean has_dollar; + register wchar_t *cq; + Name long_member_name = NULL; + + /* Internalize the name of the library */ + lib = GETNAME(lib_start, member_start - lib_start); + lib->is_member = true; + member_start++; + if (*member_start == (int) parenleft_char) { + /* This is really the "lib.a((entries))" format */ + entry = true; + member_start++; + } + /* Move the library name to the buffer where we intend to build the */ + /* "lib.a(member)" for each member */ + (void) wsncpy(buffer, lib_start, member_start - lib_start); + memberp = buffer + (member_start-lib_start); + while (1) { + long_member_name = NULL; + /* Skip leading spaces */ + for (; + (member_start < string_end) && iswspace(*member_start); + member_start++); + /* Find the end of the member name. Allow nested (). Detect $*/ + for (cq = memberp, has_dollar = false, paren_count = 0; + (member_start < string_end) && + ((*member_start != (int) parenright_char) || + (paren_count > 0)) && + !iswspace(*member_start); + *cq++ = *member_start++) { + switch (*member_start) { + case parenleft_char: + paren_count++; + break; + case parenright_char: + paren_count--; + break; + case dollar_char: + has_dollar = true; + } + } + /* Internalize the member name */ + member = GETNAME(memberp, cq - memberp); + *cq = 0; + if ((q = (wchar_t *) wsrchr(memberp, (int) slash_char)) == NULL) { + q = memberp; + } + if ((cq - q > (int) ar_member_name_len) && + !has_dollar) { + *cq++ = (int) parenright_char; + if (entry) { + *cq++ = (int) parenright_char; + } + long_member_name = GETNAME(buffer, cq - buffer); + cq = q + (int) ar_member_name_len; + } + *cq++ = (int) parenright_char; + if (entry) { + *cq++ = (int) parenright_char; + } + /* Internalize the "lib.a(member)" notation for this member */ + name = GETNAME(buffer, cq - buffer); + name->is_member = lib->is_member; + if (long_member_name != NULL) { + prop = append_prop(name, long_member_name_prop); + name->has_long_member_name = true; + prop->body.long_member_name.member_name = + long_member_name; + } + /* And add the member prop */ + prop = append_prop(name, member_prop); + prop->body.member.library = lib; + if (entry) { + /* "lib.a((entry))" notation */ + prop->body.member.entry = member; + prop->body.member.member = NULL; + } else { + /* "lib.a(member)" Notation */ + prop->body.member.entry = NULL; + prop->body.member.member = member; + } + /* Handle overflow of current_names */ + if (current_names->used == VSIZEOF(current_names->names)) { + if (current_names->next != NULL) { + current_names = current_names->next; + } else { + if (*extra_names == NULL) { + current_names = + current_names->next = + ALLOC(Name_vector); + } else { + current_names = + current_names->next = + *extra_names; + *extra_names = NULL; + } + current_names->used = 0; + current_names->next = NULL; + } + } + current_names->target_group[current_names->used] = NULL; + current_names->names[current_names->used++] = name; + while (iswspace(*member_start)) { + member_start++; + } + /* Check if there are more members */ + if ((*member_start == (int) parenright_char) || + (member_start >= string_end)) { + return current_names; + } + } + /* NOTREACHED */ +} + +/* + * normalize_name(name_string, length) + * + * Take a namestring and remove redundant ../, // and ./ constructs + * + * Return value: + * The normalized name + * + * Parameters: + * name_string Path string to normalize + * length Length of that string + * + * Global variables used: + * dot The Name ".", compared against + * dotdot The Name "..", compared against + */ +Name +normalize_name(register wchar_t *name_string, register int length) +{ + static Name dotdot; + register wchar_t *string = ALLOC_WC(length + 1); + register wchar_t *string2; + register wchar_t *cdp; + wchar_t *current_component; + Name name; + register int count; + + if (dotdot == NULL) { + MBSTOWCS(wcs_buffer, ".."); + dotdot = GETNAME(wcs_buffer, FIND_LENGTH); + } + + /* + * Copy string removing ./ and //. + * First strip leading ./ + */ + while ((length > 1) && + (name_string[0] == (int) period_char) && + (name_string[1] == (int) slash_char)) { + name_string += 2; + length -= 2; + while ((length > 0) && (name_string[0] == (int) slash_char)) { + name_string++; + length--; + } + } + /* Then copy the rest of the string removing /./ & // */ + cdp = string; + while (length > 0) { + if (((length > 2) && + (name_string[0] == (int) slash_char) && + (name_string[1] == (int) period_char) && + (name_string[2] == (int) slash_char)) || + ((length == 2) && + (name_string[0] == (int) slash_char) && + (name_string[1] == (int) period_char))) { + name_string += 2; + length -= 2; + continue; + } + if ((length > 1) && + (name_string[0] == (int) slash_char) && + (name_string[1] == (int) slash_char)) { + name_string++; + length--; + continue; + } + *cdp++ = *name_string++; + length--; + } + *cdp = (int) nul_char; + /* + * Now scan for <name>/../ and remove such combinations iff <name> + * is not another .. + * Each time something is removed, the whole process is restarted. + */ +removed_one: + name_string = string; + string2 = name_string; /*save for free*/ + current_component = + cdp = + string = + ALLOC_WC((length = wslen(name_string)) + 1); + while (length > 0) { + if (((length > 3) && + (name_string[0] == (int) slash_char) && + (name_string[1] == (int) period_char) && + (name_string[2] == (int) period_char) && + (name_string[3] == (int) slash_char)) || + ((length == 3) && + (name_string[0] == (int) slash_char) && + (name_string[1] == (int) period_char) && + (name_string[2] == (int) period_char))) { + /* Positioned on the / that starts a /.. sequence */ + if (((count = cdp - current_component) != 0) && + (exists(name = GETNAME(string, cdp - string)) > file_doesnt_exist) && + (!name->stat.is_sym_link)) { + name = GETNAME(current_component, count); + if(name != dotdot) { + cdp = current_component; + name_string += 3; + length -= 3; + if (length > 0) { + name_string++; /* skip slash */ + length--; + while (length > 0) { + *cdp++ = *name_string++; + length--; + } + } + *cdp = (int) nul_char; + retmem(string2); + goto removed_one; + } + } + } + if ((*cdp++ = *name_string++) == (int) slash_char) { + current_component = cdp; + } + length--; + } + *cdp = (int) nul_char; + if (string[0] == (int) nul_char) { + name = dot; + } else { + name = GETNAME(string, FIND_LENGTH); + } + retmem(string); + retmem(string2); + return name; +} + +/* + * find_target_groups(target_list) + * + * If a "+" was seen when the target list was scanned we need to extract + * the groups. Each target in the name vector that is a member of a + * group gets a pointer to a chain of all the members stuffed in its + * target_group vector slot + * + * Parameters: + * target_list The list of targets that contains "+" + * + * Global variables used: + * plus The Name "+", compared against + */ +Chain +find_target_groups(register Name_vector target_list, register int i, Boolean reset) +{ + static Chain target_group = NULL; + static Chain tail_target_group = NULL; + static Name *next; + static Boolean clear_target_group = false; + + if (reset) { + target_group = NULL; + tail_target_group = NULL; + clear_target_group = false; + } + + /* Scan the list of targets */ + /* If the previous target terminated a group */ + /* we flush the pointer to that member chain */ + if (clear_target_group) { + clear_target_group = false; + target_group = NULL; + } + /* Pick up a pointer to the cell with */ + /* the next target */ + if (i + 1 != target_list->used) { + next = &target_list->names[i + 1]; + } else { + next = (target_list->next != NULL) ? + &target_list->next->names[0] : NULL; + } + /* We have four states here : + * 0: No target group started and next element is not "+" + * This is not interesting. + * 1: A target group is being built and the next element + * is not "+". This terminates the group. + * 2: No target group started and the next member is "+" + * This is the first target in a group. + * 3: A target group started and the next member is a "+" + * The group continues. + */ + switch ((target_group ? 1 : 0) + + (next && (*next == plus) ? + 2 : 0)) { + case 0: /* Not target_group */ + break; + case 1: /* Last group member */ + /* We need to keep this pointer so */ + /* we can stuff it for last member */ + clear_target_group = true; + /* fall into */ + case 3: /* Middle group member */ + /* Add this target to the */ + /* current chain */ + tail_target_group->next = ALLOC(Chain); + tail_target_group = tail_target_group->next; + tail_target_group->next = NULL; + tail_target_group->name = target_list->names[i]; + break; + case 2: /* First group member */ + /* Start a new chain */ + target_group = tail_target_group = ALLOC(Chain); + target_group->next = NULL; + target_group->name = target_list->names[i]; + break; + } + /* Stuff the current chain, if any, in the */ + /* targets group slot */ + target_list->target_group[i] = target_group; + if ((next != NULL) && + (*next == plus)) { + *next = NULL; + } + return (tail_target_group); +} + +/* + * enter_dependencies(target, target_group, depes, command, separator) + * + * Take one target and a list of dependencies and process the whole thing. + * The target might be special in some sense in which case that is handled + * + * Parameters: + * target The target we want to enter + * target_group Non-NULL if target is part of a group this time + * depes A list of dependencies for the target + * command The command the target should be entered with + * separator Indicates if this is a ":" or a "::" rule + * + * Static variables used: + * built_last_make_run_seen If the previous target was + * .BUILT_LAST_MAKE_RUN we say to rewrite + * the state file later on + * + * Global variables used: + * command_changed Set to indicate if .make.state needs rewriting + * default_target_to_build Set to the target if reading makefile + * and this is the first regular target + * force The Name " FORCE", used with "::" targets + * makefile_type We do different things for makefile vs. report + * not_auto The Name ".NOT_AUTO", compared against + * recursive_name The Name ".RECURSIVE", compared against + * temp_file_number Used to figure out when to clear stale + * automatic dependencies + * trace_reader Indicates that we should echo stuff we read + */ +void +enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator) +{ + register int i; + register Property line; + Name name; + Name directory; + wchar_t *namep; + char *mb_namep; + Dependency dp; + Dependency *dpp; + Property line2; + wchar_t relative[MAXPATHLEN]; + register int recursive_state; + Boolean register_as_auto; + Boolean not_auto_found; + char *slash; + Wstring depstr; + + /* Check if this is a .RECURSIVE line */ + if ((depes->used >= 3) && + (depes->names[0] == recursive_name)) { +#ifdef NSE + nse_did_recursion= true; +#endif + target->has_recursive_dependency = true; + depes->names[0] = NULL; + recursive_state = 0; + dp = NULL; + dpp = &dp; + /* Read the dependencies. They are "<directory> <target-made>*/ + /* <makefile>*" */ + for (; depes != NULL; depes = depes->next) { + for (i = 0; i < depes->used; i++) { + if (depes->names[i] != NULL) { + switch (recursive_state++) { + case 0: /* Directory */ + { + depstr.init(depes->names[i]); + make_relative(depstr.get_string(), + relative); + directory = + GETNAME(relative, + FIND_LENGTH); + } + break; + case 1: /* Target */ + name = depes->names[i]; + break; + default: /* Makefiles */ + *dpp = ALLOC(Dependency); + (*dpp)->next = NULL; + (*dpp)->name = depes->names[i]; + (*dpp)->automatic = false; + (*dpp)->stale = false; + (*dpp)->built = false; + dpp = &((*dpp)->next); + break; + } + } + } + } + /* Check if this recursion already has been reported else */ + /* enter the recursive prop for the target */ + /* The has_built flag is used to tell if this .RECURSIVE */ + /* was discovered from this run (read from a tmp file) */ + /* or was from discovered from the original .make.state */ + /* file */ + for (line = get_prop(target->prop, recursive_prop); + line != NULL; + line = get_prop(line->next, recursive_prop)) { + if ((line->body.recursive.directory == directory) && + (line->body.recursive.target == name)) { + line->body.recursive.makefiles = dp; + line->body.recursive.has_built = + (Boolean) + (makefile_type == reading_cpp_file); + return; + } + } + line2 = append_prop(target, recursive_prop); + line2->body.recursive.directory = directory; + line2->body.recursive.target = name; + line2->body.recursive.makefiles = dp; + line2->body.recursive.has_built = + (Boolean) (makefile_type == reading_cpp_file); + line2->body.recursive.in_depinfo = false; + return; + } + /* If this is the first target that doesnt start with a "." in the */ + /* makefile we remember that */ + Wstring tstr(target); + wchar_t * wcb = tstr.get_string(); + if ((makefile_type == reading_makefile) && + (default_target_to_build == NULL) && + ((wcb[0] != (int) period_char) || + wschr(wcb, (int) slash_char))) { + +/* BID 1181577: $(EMPTY_MACRO) + $(EMPTY_MACRO): +** The target with empty name cannot be default_target_to_build +*/ + if (target->hash.length != 0) + default_target_to_build = target; + } + /* Check if the line is ":" or "::" */ + if (makefile_type == reading_makefile) { + if (target->colons == no_colon) { + target->colons = separator; + } else { + if (target->colons != separator) { + fatal_reader(catgets(catd, 1, 92, ":/:: conflict for target `%s'"), + target->string_mb); + } + } + if (target->colons == two_colon) { + if (depes->used == 0) { + /* If this is a "::" type line with no */ + /* dependencies we add one "FRC" type */ + /* dependency for free */ + depes->used = 1; /* Force :: targets with no + * depes to always run */ + depes->names[0] = force; + } + /* Do not delete "::" type targets when interrupted */ + target->stat.is_precious = true; + /* + * Build a synthetic target "<number>%target" + * for "target". + */ + mb_namep = getmem((int) (strlen(target->string_mb) + 10)); + namep = ALLOC_WC((int) (target->hash.length + 10)); + slash = strrchr(target->string_mb, (int) slash_char); + if (slash == NULL) { + (void) sprintf(mb_namep, + "%d@%s", + target->colon_splits++, + target->string_mb); + } else { + *slash = 0; + (void) sprintf(mb_namep, + "%s/%d@%s", + target->string_mb, + target->colon_splits++, + slash + 1); + *slash = (int) slash_char; + } + MBSTOWCS(namep, mb_namep); + retmem_mb(mb_namep); + name = GETNAME(namep, FIND_LENGTH); + retmem(namep); + if (trace_reader) { + (void) printf("%s:\t", target->string_mb); + } + /* Make "target" depend on "<number>%target */ + line2 = maybe_append_prop(target, line_prop); + enter_dependency(line2, name, true); + line2->body.line.target = target; + /* Put a prop on "<number>%target that makes */ + /* appear as "target" */ + /* when it is processed */ + maybe_append_prop(name, target_prop)-> + body.target.target = target; + target->is_double_colon_parent = true; + name->is_double_colon = true; + name->has_target_prop = true; + if (trace_reader) { + (void) printf("\n"); + } + (target = name)->stat.is_file = true; + } + } + /* This really is a regular dependency line. Just enter it */ + line = maybe_append_prop(target, line_prop); + line->body.line.target = target; + /* Depending on what kind of makefile we are reading we have to */ + /* treat things differently */ + switch (makefile_type) { + case reading_makefile: + /* Reading regular makefile. Just notice whether this */ + /* redefines the rule for the target */ + if (command != NULL) { + if (line->body.line.command_template != NULL) { + line->body.line.command_template_redefined = + true; + if ((wcb[0] == (int) period_char) && + !wschr(wcb, (int) slash_char)) { + line->body.line.command_template = + command; + } + } else { + line->body.line.command_template = command; + } + } else { + if ((wcb[0] == (int) period_char) && + !wschr(wcb, (int) slash_char)) { + line->body.line.command_template = command; + } + } + break; + case rereading_statefile: + /* Rereading the statefile. We only enter thing that changed */ + /* since the previous time we read it */ + if (!built_last_make_run_seen) { + for (Cmd_line next, cmd = command; cmd != NULL; cmd = next) { + next = cmd->next; + free(cmd); + } + return; + } + built_last_make_run_seen = false; + command_changed = true; + target->ran_command = true; + case reading_statefile: + /* Reading the statefile for the first time. Enter the rules */ + /* as "Commands used" not "templates to use" */ + if (command != NULL) { + for (Cmd_line next, cmd = line->body.line.command_used; + cmd != NULL; cmd = next) { + next = cmd->next; + free(cmd); + } + line->body.line.command_used = command; + } + case reading_cpp_file: + /* Reading report file from programs that reports */ + /* dependencies. If this is the first time the target is */ + /* read from this reportfile we clear all old */ + /* automatic depes */ + if (target->temp_file_number == temp_file_number) { + break; + } + target->temp_file_number = temp_file_number; + command_changed = true; + if (line != NULL) { + for (dp = line->body.line.dependencies; + dp != NULL; + dp = dp->next) { + if (dp->automatic) { + dp->stale = true; + } + } + } + break; + default: + fatal_reader(catgets(catd, 1, 93, "Internal error. Unknown makefile type %d"), + makefile_type); + } + /* A target may only be involved in one target group */ + if (line->body.line.target_group != NULL) { + if (target_group != NULL) { + fatal_reader(catgets(catd, 1, 94, "Too many target groups for target `%s'"), + target->string_mb); + } + } else { + line->body.line.target_group = target_group; + } + + if (trace_reader) { + (void) printf("%s:\t", target->string_mb); + } + /* Enter the dependencies */ + register_as_auto = BOOLEAN(makefile_type != reading_makefile); + not_auto_found = false; + for (; + (depes != NULL) && !not_auto_found; + depes = depes->next) { + for (i = 0; i < depes->used; i++) { + /* the dependency .NOT_AUTO signals beginning of + * explicit dependancies which were put at end of + * list in .make.state file - we stop entering + * dependencies at this point + */ + if (depes->names[i] == not_auto) { + not_auto_found = true; + break; + } + enter_dependency(line, + depes->names[i], + register_as_auto); + } + } + if (trace_reader) { + (void) printf("\n"); + print_rule(command); + } +} + +/* + * enter_dependency(line, depe, automatic) + * + * Enter one dependency. Do not enter duplicates. + * + * Parameters: + * line The line block that the dependeny is + * entered for + * depe The dependency to enter + * automatic Used to set the field "automatic" + * + * Global variables used: + * makefile_type We do different things for makefile vs. report + * trace_reader Indicates that we should echo stuff we read + * wait_name The Name ".WAIT", compared against + */ +void +enter_dependency(Property line, register Name depe, Boolean automatic) +{ + register Dependency dp; + register Dependency *insert; + + if (trace_reader) { + (void) printf("%s ", depe->string_mb); + } + /* Find the end of the list and check for duplicates */ + for (insert = &line->body.line.dependencies, dp = *insert; + dp != NULL; + insert = &dp->next, dp = *insert) { + if ((dp->name == depe) && (depe != wait_name)) { + if (dp->automatic) { + dp->automatic = automatic; + if (automatic) { + dp->built = false; + depe->stat.is_file = true; +#ifdef NSE + depe->has_parent= true; + depe->is_target= true; +#endif + } + } + dp->stale = false; + return; + } + } + /* Insert the new dependency since we couldnt find it */ + dp = *insert = ALLOC(Dependency); + dp->name = depe; + dp->next = NULL; + dp->automatic = automatic; + dp->stale = false; + dp->built = false; + depe->stat.is_file = true; +#ifdef NSE + depe->has_parent= true; + depe->is_target= true; +#endif + + if ((makefile_type == reading_makefile) && + (line != NULL) && + (line->body.line.target != NULL)) { + line->body.line.target->has_regular_dependency = true; +#ifdef NSE + line->body.line.target->is_target= true; +#endif + } +} + +/* + * enter_percent(target, depes, command) + * + * Enter "x%y : a%b" type lines + * % patterns are stored in four parts head and tail for target and source + * + * Parameters: + * target Left hand side of pattern + * depes The dependency list with the rh pattern + * command The command for the pattern + * + * Global variables used: + * empty_name The Name "", compared against + * percent_list The list of all percent rules, added to + * trace_reader Indicates that we should echo stuff we read + */ +Percent +enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command) +{ + register Percent result = ALLOC(Percent); + register Percent depe; + register Percent *depe_tail = &result->dependencies; + register Percent *insert; + register wchar_t *cp, *cp1; + Name_vector nvp; + int i; + int pattern; + + result->next = NULL; + result->patterns = NULL; + result->patterns_total = 0; + result->command_template = command; + result->being_expanded = false; + result->name = target; + result->dependencies = NULL; + result->target_group = target_group; + + /* get patterns count */ + Wstring wcb(target); + cp = wcb.get_string(); + while (true) { + cp = (wchar_t *) wschr(cp, (int) percent_char); + if (cp != NULL) { + result->patterns_total++; + cp++; + } else { + break; + } + } + result->patterns_total++; + + /* allocate storage for patterns */ + result->patterns = (Name *) getmem(sizeof(Name) * result->patterns_total); + + /* then create patterns */ + cp = wcb.get_string(); + pattern = 0; + while (true) { + cp1 = (wchar_t *) wschr(cp, (int) percent_char); + if (cp1 != NULL) { + result->patterns[pattern] = GETNAME(cp, cp1 - cp); + cp = cp1 + 1; + pattern++; + } else { + result->patterns[pattern] = GETNAME(cp, (int) target->hash.length - (cp - wcb.get_string())); + break; + } + } + + Wstring wcb1; + + /* build dependencies list */ + for (nvp = depes; nvp != NULL; nvp = nvp->next) { + for (i = 0; i < nvp->used; i++) { + depe = ALLOC(Percent); + depe->next = NULL; + depe->patterns = NULL; + depe->patterns_total = 0; + depe->name = nvp->names[i]; + depe->dependencies = NULL; + depe->command_template = NULL; + depe->being_expanded = false; + depe->target_group = NULL; + + *depe_tail = depe; + depe_tail = &depe->next; + + if (depe->name->percent) { + /* get patterns count */ + wcb1.init(depe->name); + cp = wcb1.get_string(); + while (true) { + cp = (wchar_t *) wschr(cp, (int) percent_char); + if (cp != NULL) { + depe->patterns_total++; + cp++; + } else { + break; + } + } + depe->patterns_total++; + + /* allocate storage for patterns */ + depe->patterns = (Name *) getmem(sizeof(Name) * depe->patterns_total); + + /* then create patterns */ + cp = wcb1.get_string(); + pattern = 0; + while (true) { + cp1 = (wchar_t *) wschr(cp, (int) percent_char); + if (cp1 != NULL) { + depe->patterns[pattern] = GETNAME(cp, cp1 - cp); + cp = cp1 + 1; + pattern++; + } else { + depe->patterns[pattern] = GETNAME(cp, (int) depe->name->hash.length - (cp - wcb1.get_string())); + break; + } + } + } + } + } + + /* Find the end of the percent list and append the new pattern */ + for (insert = &percent_list; (*insert) != NULL; insert = &(*insert)->next); + *insert = result; + + if (trace_reader) { + (void) printf("%s:", result->name->string_mb); + + for (depe = result->dependencies; depe != NULL; depe = depe->next) { + (void) printf(" %s", depe->name->string_mb); + } + + (void) printf("\n"); + + print_rule(command); + } + + return result; +} + +/* + * enter_dyntarget(target) + * + * Enter "$$(MACRO) : b" type lines + * + * Parameters: + * target Left hand side of pattern + * + * Global variables used: + * dyntarget_list The list of all percent rules, added to + * trace_reader Indicates that we should echo stuff we read + */ +Dyntarget +enter_dyntarget(register Name target) +{ + register Dyntarget result = ALLOC(Dyntarget); + Dyntarget p; + Dyntarget *insert; + int i; + + result->next = NULL; + result->name = target; + + + /* Find the end of the dyntarget list and append the new pattern */ + for (insert = &dyntarget_list, p = *insert; + p != NULL; + insert = &p->next, p = *insert); + *insert = result; + + if (trace_reader) { + (void) printf(NOCATGETS("Dynamic target %s:\n"), result->name->string_mb); + } + return( result); +} + + +/* + * special_reader(target, depes, command) + * + * Read the pseudo targets make knows about + * This handles the special targets that should not be entered as regular + * target/dependency sets. + * + * Parameters: + * target The special target + * depes The list of dependencies it was entered with + * command The command it was entered with + * + * Static variables used: + * built_last_make_run_seen Set to indicate .BUILT_LAST... seen + * + * Global variables used: + * all_parallel Set to indicate that everything runs parallel + * svr4 Set when ".SVR4" target is read + * svr4_name The Name ".SVR4" + * posix Set when ".POSIX" target is read + * posix_name The Name ".POSIX" + * current_make_version The Name "<current version number>" + * default_rule Set when ".DEFAULT" target is read + * default_rule_name The Name ".DEFAULT", used for tracing + * dot_keep_state The Name ".KEEP_STATE", used for tracing + * ignore_errors Set if ".IGNORE" target is read + * ignore_name The Name ".IGNORE", used for tracing + * keep_state Set if ".KEEP_STATE" target is read + * no_parallel_name The Name ".NO_PARALLEL", used for tracing + * only_parallel Set to indicate only some targets runs parallel + * parallel_name The Name ".PARALLEL", used for tracing + * precious The Name ".PRECIOUS", used for tracing + * sccs_get_name The Name ".SCCS_GET", used for tracing + * sccs_get_posix_name The Name ".SCCS_GET_POSIX", used for tracing + * get_name The Name ".GET", used for tracing + * sccs_get_rule Set when ".SCCS_GET" target is read + * silent Set when ".SILENT" target is read + * silent_name The Name ".SILENT", used for tracing + * trace_reader Indicates that we should echo stuff we read + */ +void +special_reader(Name target, register Name_vector depes, Cmd_line command) +{ + register int n; + + switch (target->special_reader) { + + case svr4_special: + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 98, "Illegal dependencies for target `%s'"), + target->string_mb); + } + svr4 = true; + posix = false; + keep_state = false; + all_parallel = false; + only_parallel = false; + if (trace_reader) { + (void) printf("%s:\n", svr4_name->string_mb); + } + break; + + case posix_special: + if(svr4) + break; + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 99, "Illegal dependencies for target `%s'"), + target->string_mb); + } + posix = true; + /* with posix on, use the posix get rule */ + sccs_get_rule = sccs_get_posix_rule; + /* turn keep state off being SunPro make specific */ + keep_state = false; + #if defined(SUN5_0) + /* Use /usr/xpg4/bin/sh on Solaris */ + MBSTOWCS(wcs_buffer, NOCATGETS("/usr/xpg4/bin/sh")); + (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false); + #endif + if (trace_reader) { + (void) printf("%s:\n", posix_name->string_mb); + } + break; + + case built_last_make_run_special: + built_last_make_run_seen = true; + break; + + case default_special: + if (depes->used != 0) { + warning(catgets(catd, 1, 100, "Illegal dependency list for target `%s'"), + target->string_mb); + } + default_rule = command; + if (trace_reader) { + (void) printf("%s:\n", + default_rule_name->string_mb); + print_rule(command); + } + break; + +#ifdef NSE + case derived_src_special: + for (; depes != NULL; depes= depes->next) + for (n= 0; n < depes->used; n++) { + if (trace_reader) + (void)printf("%s:\t%s\n", + precious->string_mb, + depes->names[n]->string_mb); + depes->names[n]->stat.is_derived_src= true; + }; + break; +#endif + + case ignore_special: + if ((depes->used != 0) &&(!posix)){ + fatal_reader(catgets(catd, 1, 101, "Illegal dependencies for target `%s'"), + target->string_mb); + } + if (depes->used == 0) + { + ignore_errors_all = true; + } + if(svr4) { + ignore_errors_all = true; + break; + } + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + depes->names[n]->ignore_error_mode = true; + } + } + if (trace_reader) { + (void) printf("%s:\n", ignore_name->string_mb); + } + break; + + case keep_state_special: + if(svr4) + break; + /* ignore keep state, being SunPro make specific */ + if(posix) + break; + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 102, "Illegal dependencies for target `%s'"), + target->string_mb); + } + keep_state = true; + if (trace_reader) { + (void) printf("%s:\n", + dot_keep_state->string_mb); + } + break; + + case keep_state_file_special: + if(svr4) + break; + if(posix) + break; + /* it's not necessary to specify KEEP_STATE, if this + ** is given, so set the keep_state. + */ + keep_state = true; + if (depes->used != 0) { + if((!make_state) ||(!strcmp(make_state->string_mb,NOCATGETS(".make.state")))) { + make_state = depes->names[0]; + } + } + break; + case make_version_special: + if(svr4) + break; + if (depes->used != 1) { + fatal_reader(catgets(catd, 1, 103, "Illegal dependency list for target `%s'"), + target->string_mb); + } + if (depes->names[0] != current_make_version) { + /* + * Special case the fact that version 1.0 and 1.1 + * are identical. + */ + if (!IS_EQUAL(depes->names[0]->string_mb, + NOCATGETS("VERSION-1.1")) || + !IS_EQUAL(current_make_version->string_mb, + NOCATGETS("VERSION-1.0"))) { + /* + * Version mismatches should cause the + * .make.state file to be skipped. + * This is currently not true - it is read + * anyway. + */ + warning(catgets(catd, 1, 104, "Version mismatch between current version `%s' and `%s'"), + current_make_version->string_mb, + depes->names[0]->string_mb); + } + } + break; + + case no_parallel_special: + if(svr4) + break; + /* Set the no_parallel bit for all the targets on */ + /* the dependency list */ + if (depes->used == 0) { + /* only those explicitly made parallel */ + only_parallel = true; + all_parallel = false; + } + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + if (trace_reader) { + (void) printf("%s:\t%s\n", + no_parallel_name->string_mb, + depes->names[n]->string_mb); + } + depes->names[n]->no_parallel = true; + depes->names[n]->parallel = false; + } + } + break; + + case parallel_special: + if(svr4) + break; + if (depes->used == 0) { + /* everything runs in parallel */ + all_parallel = true; + only_parallel = false; + } + /* Set the parallel bit for all the targets on */ + /* the dependency list */ + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + if (trace_reader) { + (void) printf("%s:\t%s\n", + parallel_name->string_mb, + depes->names[n]->string_mb); + } + depes->names[n]->parallel = true; + depes->names[n]->no_parallel = false; + } + } + break; + + case localhost_special: + if(svr4) + break; + /* Set the no_parallel bit for all the targets on */ + /* the dependency list */ + if (depes->used == 0) { + /* only those explicitly made parallel */ + only_parallel = true; + all_parallel = false; + } + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + if (trace_reader) { + (void) printf("%s:\t%s\n", + localhost_name->string_mb, + depes->names[n]->string_mb); + } + depes->names[n]->no_parallel = true; + depes->names[n]->parallel = false; + depes->names[n]->localhost = true; + } + } + break; + + case precious_special: + if (depes->used == 0) { + /* everything is precious */ + all_precious = true; + } else { + all_precious = false; + } + if(svr4) { + all_precious = true; + break; + } + /* Set the precious bit for all the targets on */ + /* the dependency list */ + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + if (trace_reader) { + (void) printf("%s:\t%s\n", + precious->string_mb, + depes->names[n]->string_mb); + } + depes->names[n]->stat.is_precious = true; + } + } + break; + + case sccs_get_special: + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 105, "Illegal dependencies for target `%s'"), + target->string_mb); + } + sccs_get_rule = command; + sccs_get_org_rule = command; + if (trace_reader) { + (void) printf("%s:\n", sccs_get_name->string_mb); + print_rule(command); + } + break; + + case sccs_get_posix_special: + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 106, "Illegal dependencies for target `%s'"), + target->string_mb); + } + sccs_get_posix_rule = command; + if (trace_reader) { + (void) printf("%s:\n", sccs_get_posix_name->string_mb); + print_rule(command); + } + break; + + case get_posix_special: + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 107, "Illegal dependencies for target `%s'"), + target->string_mb); + } + get_posix_rule = command; + if (trace_reader) { + (void) printf("%s:\n", get_posix_name->string_mb); + print_rule(command); + } + break; + + case get_special: + if(!svr4) { + break; + } + if (depes->used != 0) { + fatal_reader(catgets(catd, 1, 108, "Illegal dependencies for target `%s'"), + target->string_mb); + } + get_rule = command; + sccs_get_rule = command; + if (trace_reader) { + (void) printf("%s:\n", get_name->string_mb); + print_rule(command); + } + break; + + case silent_special: + if ((depes->used != 0) && (!posix)){ + fatal_reader(catgets(catd, 1, 109, "Illegal dependencies for target `%s'"), + target->string_mb); + } + if (depes->used == 0) + { + silent_all = true; + } + if(svr4) { + silent_all = true; + break; + } + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + depes->names[n]->silent_mode = true; + } + } + if (trace_reader) { + (void) printf("%s:\n", silent_name->string_mb); + } + break; + + case suffixes_special: + read_suffixes_list(depes); + break; + + default: + + fatal_reader(catgets(catd, 1, 110, "Internal error: Unknown special reader")); + } +} + +/* + * read_suffixes_list(depes) + * + * Read the special list .SUFFIXES. If it is empty the old list is + * cleared. Else the new one is appended. Suffixes with ~ are extracted + * and marked. + * + * Parameters: + * depes The list of suffixes + * + * Global variables used: + * hashtab The central hashtable for Names. + * suffixes The list of suffixes, set or appended to + * suffixes_name The Name ".SUFFIXES", used for tracing + * trace_reader Indicates that we should echo stuff we read + */ +static void +read_suffixes_list(register Name_vector depes) +{ + register int n; + register Dependency dp; + register Dependency *insert_dep; + register Name np; + Name np2; + register Boolean first = true; + + if (depes->used == 0) { + /* .SUFFIXES with no dependency list clears the */ + /* suffixes list */ + for (Name_set::iterator np = hashtab.begin(), e = hashtab.end(); np != e; np++) { + np->with_squiggle = + np->without_squiggle = + false; + } + suffixes = NULL; + if (trace_reader) { + (void) printf("%s:\n", suffixes_name->string_mb); + } + return; + } + Wstring str; + /* Otherwise we append to the list */ + for (; depes != NULL; depes = depes->next) { + for (n = 0; n < depes->used; n++) { + np = depes->names[n]; + /* Find the end of the list and check if the */ + /* suffix already has been entered */ + for (insert_dep = &suffixes, dp = *insert_dep; + dp != NULL; + insert_dep = &dp->next, dp = *insert_dep) { + if (dp->name == np) { + goto duplicate_suffix; + } + } + if (trace_reader) { + if (first) { + (void) printf("%s:\t", + suffixes_name->string_mb); + first = false; + } + (void) printf("%s ", depes->names[n]->string_mb); + } + if(!(posix|svr4)) { + /* If the suffix is suffixed with "~" we */ + /* strip that and mark the suffix nameblock */ + str.init(np); + wchar_t * wcb = str.get_string(); + if (wcb[np->hash.length - 1] == + (int) tilde_char) { + np2 = GETNAME(wcb, + (int)(np->hash.length - 1)); + np2->with_squiggle = true; + if (np2->without_squiggle) { + continue; + } + np = np2; + } + } + np->without_squiggle = true; + /* Add the suffix to the list */ + dp = *insert_dep = ALLOC(Dependency); + insert_dep = &dp->next; + dp->next = NULL; + dp->name = np; + dp->built = false; + duplicate_suffix:; + } + } + if (trace_reader) { + (void) printf("\n"); + } +} + +/* + * make_relative(to, result) + * + * Given a file name compose a relative path name from it to the + * current directory. + * + * Parameters: + * to The path we want to make relative + * result Where to put the resulting relative path + * + * Global variables used: + */ +static void +make_relative(wchar_t *to, wchar_t *result) +{ + wchar_t *from; + wchar_t *allocated; + wchar_t *cp; + wchar_t *tocomp; + int ncomps; + int i; + int len; + + /* Check if the path is already relative. */ + if (to[0] != (int) slash_char) { + (void) wscpy(result, to); + return; + } + + MBSTOWCS(wcs_buffer, get_current_path()); + from = allocated = (wchar_t *) wsdup(wcs_buffer); + + /* + * Find the number of components in the from name. + * ncomp = number of slashes + 1. + */ + ncomps = 1; + for (cp = from; *cp != (int) nul_char; cp++) { + if (*cp == (int) slash_char) { + ncomps++; + } + } + + /* + * See how many components match to determine how many "..", + * if any, will be needed. + */ + result[0] = (int) nul_char; + tocomp = to; + while ((*from != (int) nul_char) && (*from == *to)) { + if (*from == (int) slash_char) { + ncomps--; + tocomp = &to[1]; + } + from++; + to++; + } + + /* + * Now for some special cases. Check for exact matches and + * for either name terminating exactly. + */ + if (*from == (int) nul_char) { + if (*to == (int) nul_char) { + MBSTOWCS(wcs_buffer, "."); + (void) wscpy(result, wcs_buffer); + retmem(allocated); + return; + } + if (*to == (int) slash_char) { + ncomps--; + tocomp = &to[1]; + } + } else if ((*from == (int) slash_char) && (*to == (int) nul_char)) { + ncomps--; + tocomp = to; + } + /* Add on the ".."s. */ + for (i = 0; i < ncomps; i++) { + MBSTOWCS(wcs_buffer, "../"); + (void) wscat(result, wcs_buffer); + } + + /* Add on the remainder of the to name, if any. */ + if (*tocomp == (int) nul_char) { + len = wslen(result); + result[len - 1] = (int) nul_char; + } else { + (void) wscat(result, tocomp); + } + retmem(allocated); + return; +} + +/* + * print_rule(command) + * + * Used when tracing the reading of rules + * + * Parameters: + * command Command to print + * + * Global variables used: + */ +static void +print_rule(register Cmd_line command) +{ + for (; command != NULL; command = command->next) { + (void) printf("\t%s\n", command->command_line->string_mb); + } +} + +/* + * enter_conditional(target, name, value, append) + * + * Enter "target := MACRO= value" constructs + * + * Parameters: + * target The target the macro is for + * name The name of the macro + * value The value for the macro + * append Indicates if the assignment is appending or not + * + * Global variables used: + * conditionals A special Name that stores all conditionals + * where the target is a % pattern + * trace_reader Indicates that we should echo stuff we read + */ +void +enter_conditional(register Name target, Name name, Name value, register Boolean append) +{ + register Property conditional; + static int sequence; + Name orig_target = target; + + if (name == target_arch) { + enter_conditional(target, virtual_root, virtual_root, false); + } + + if (target->percent) { + target = conditionals; + } + + if (name->colon) { + sh_transform(&name, &value); + } + + /* Count how many conditionals we must activate before building the */ + /* target */ + if (target->percent) { + target = conditionals; + } + + target->conditional_cnt++; + maybe_append_prop(name, macro_prop)->body.macro.is_conditional = true; + /* Add the property for the target */ + conditional = append_prop(target, conditional_prop); + conditional->body.conditional.target = orig_target; + conditional->body.conditional.name = name; + conditional->body.conditional.value = value; + conditional->body.conditional.sequence = sequence++; + conditional->body.conditional.append = append; + if (trace_reader) { + if (value == NULL) { + (void) printf("%s := %s %c=\n", + target->string_mb, + name->string_mb, + append ? + (int) plus_char : (int) space_char); + } else { + (void) printf("%s := %s %c= %s\n", + target->string_mb, + name->string_mb, + append ? + (int) plus_char : (int) space_char, + value->string_mb); + } + } +} + +/* + * enter_equal(name, value, append) + * + * Enter "MACRO= value" constructs + * + * Parameters: + * name The name of the macro + * value The value for the macro + * append Indicates if the assignment is appending or not + * + * Global variables used: + * trace_reader Indicates that we should echo stuff we read + */ +void +enter_equal(Name name, Name value, register Boolean append) +{ + wchar_t *string; + Name temp; + + if (name->colon) { + sh_transform(&name, &value); + } + (void) SETVAR(name, value, append); + + /* if we're setting FC, we want to set F77 to the same value. */ + Wstring nms(name); + wchar_t * wcb = nms.get_string(); + string = wcb; + if (string[0]=='F' && + string[1]=='C' && + string[2]=='\0') { + MBSTOWCS(wcs_buffer, NOCATGETS("F77")); + temp = GETNAME(wcs_buffer, FIND_LENGTH); + (void) SETVAR(temp, value, append); +/* + fprintf(stderr, catgets(catd, 1, 111, "warning: FC is obsolete, use F77 instead\n")); + */ + } + + if (trace_reader) { + if (value == NULL) { + (void) printf("%s %c=\n", + name->string_mb, + append ? + (int) plus_char : (int) space_char); + } else { + (void) printf("%s %c= %s\n", + name->string_mb, + append ? + (int) plus_char : (int) space_char, + value->string_mb); + } + } +} + +/* + * sh_transform(name, value) + * + * Parameters: + * name The name of the macro we might transform + * value The value to transform + * + */ +static void +sh_transform(Name *name, Name *value) +{ + /* Check if we need :sh transform */ + wchar_t *colon; + String_rec command; + String_rec destination; + wchar_t buffer[1000]; + wchar_t buffer1[1000]; + + static wchar_t colon_sh[4]; + static wchar_t colon_shell[7]; + + if (colon_sh[0] == (int) nul_char) { + MBSTOWCS(colon_sh, NOCATGETS(":sh")); + MBSTOWCS(colon_shell, NOCATGETS(":shell")); + } + Wstring nms((*name)); + wchar_t * wcb = nms.get_string(); + + colon = (wchar_t *) wsrchr(wcb, (int) colon_char); + if ((colon != NULL) && (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell))) { + INIT_STRING_FROM_STACK(destination, buffer); + + if(*value == NULL) { + buffer[0] = 0; + } else { + Wstring wcb1((*value)); + if (IS_WEQUAL(colon, colon_shell)) { + INIT_STRING_FROM_STACK(command, buffer1); + expand_value(*value, &command, false); + } else { + command.text.p = wcb1.get_string() + (*value)->hash.length; + command.text.end = command.text.p; + command.buffer.start = wcb1.get_string(); + command.buffer.end = command.text.p; + } + sh_command2string(&command, &destination); + } + + (*value) = GETNAME(destination.buffer.start, FIND_LENGTH); + *colon = (int) nul_char; + (*name) = GETNAME(wcb, FIND_LENGTH); + *colon = (int) colon_char; + } +} + +/* + * fatal_reader(format, args...) + * + * Parameters: + * format printf style format string + * args arguments to match the format + * + * Global variables used: + * file_being_read Name of the makefile being read + * line_number Line that is being read + * report_pwd Indicates whether current path should be shown + * temp_file_name When reading tempfile we report that name + */ +/*VARARGS*/ +void +fatal_reader(char * pattern, ...) +{ + va_list args; + char message[1000]; + + va_start(args, pattern); + if (file_being_read != NULL) { + WCSTOMBS(mbs_buffer, file_being_read); + if (line_number != 0) { + (void) sprintf(message, + catgets(catd, 1, 112, "%s, line %d: %s"), + mbs_buffer, + line_number, + pattern); + } else { + (void) sprintf(message, + "%s: %s", + mbs_buffer, + pattern); + } + pattern = message; + } + + (void) fflush(stdout); +#ifdef DISTRIBUTED + (void) fprintf(stderr, catgets(catd, 1, 113, "dmake: Fatal error in reader: ")); +#else + (void) fprintf(stderr, catgets(catd, 1, 238, "make: Fatal error in reader: ")); +#endif + (void) vfprintf(stderr, pattern, args); + (void) fprintf(stderr, "\n"); + va_end(args); + + if (temp_file_name != NULL) { + (void) fprintf(stderr, +#ifdef DISTRIBUTED + catgets(catd, 1, 114, "dmake: Temp-file %s not removed\n"), +#else + catgets(catd, 1, 239, "make: Temp-file %s not removed\n"), +#endif + temp_file_name->string_mb); + temp_file_name = NULL; + } + + if (report_pwd) { + (void) fprintf(stderr, + catgets(catd, 1, 115, "Current working directory %s\n"), + get_current_path()); + } + (void) fflush(stderr); +#if defined(SUN5_0) || defined(HP_UX) + exit_status = 1; +#endif + exit(1); +} + diff --git a/usr/src/make_src/Make/bin/make/common/rep.cc b/usr/src/make_src/Make/bin/make/common/rep.cc new file mode 100644 index 0000000..6ad4007 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/rep.cc @@ -0,0 +1,529 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)rep.cc 1.25 06/12/12 + */ + +#pragma ident "@(#)rep.cc 1.25 06/12/12" + +/* + * rep.c + * + * This file handles the .nse_depinfo file + */ + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/misc.h> /* retmem() */ +#include <vroot/report.h> /* NSE_DEPINFO */ + +/* + * Static variables + */ +static Recursive_make recursive_list; +static Recursive_make *bpatch = &recursive_list; +static Boolean changed; + +/* + * File table of contents + */ + + +/* + * report_recursive_init() + * + * Read the .nse_depinfo file and make a list of all the + * .RECURSIVE entries. + * + * Parameters: + * + * Static variables used: + * bpatch Points to slot where next cell should be added + * + * Global variables used: + * recursive_name The Name ".RECURSIVE", compared against + */ + +void +report_recursive_init(void) +{ + char *search_dir; + char nse_depinfo[MAXPATHLEN]; + FILE *fp; + int line_size, line_index; + wchar_t *line; + wchar_t *bigger_line; + wchar_t *colon; + wchar_t *dollar; + Recursive_make rp; + + /* + * This routine can be called more than once, don't do + * anything after the first time. + */ + if (depinfo_already_read) { + return; + } else { + depinfo_already_read = true; + } + + search_dir = getenv(NOCATGETS("NSE_DEP")); + if (search_dir == NULL) { + return; + } + (void) sprintf(nse_depinfo, "%s/%s", search_dir, NSE_DEPINFO); + fp = fopen(nse_depinfo, "r"); + if (fp == NULL) { + return; + } + line_size = MAXPATHLEN; + line_index = line_size - 1; + line = ALLOC_WC(line_size); + Wstring rns(recursive_name); + wchar_t * wcb = rns.get_string(); + while (fgetws(line, line_size, fp) != NULL) { + while (wslen(line) == line_index) { + if (line[wslen(line) - 1] == '\n') { + continue; + } + bigger_line = ALLOC_WC(2 * line_size); + wscpy(bigger_line, line); + retmem(line); + line = bigger_line; + if (fgetws(&line[line_index], line_size, fp) == NULL) + continue; + line_index = 2 * line_index; + line_size = 2 * line_size; + } + + colon = (wchar_t *) wschr(line, (int) colon_char); + if (colon == NULL) { + continue; + } + dollar = (wchar_t *) wschr(line, (int) dollar_char); + line[wslen(line) - 1] = (int) nul_char; + if (IS_WEQUALN(&colon[2], wcb, + (int) recursive_name->hash.length)) { + /* + * If this entry is an old entry, ignore it + */ + MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); + if (dollar == NULL || + !IS_WEQUALN(wcs_buffer, (dollar+1) - VER_LEN, VER_LEN)){ + continue; + } + rp = ALLOC(Recursive_make); + (void) memset((char *) rp, 0, sizeof (Recursive_make_rec)); + /* + * set conditional_macro_string if string is present + */ + rp->oldline = (wchar_t *) wsdup(line); + if ( dollar != NULL ){ + rp->cond_macrostring = + (wchar_t *) wsdup(dollar - VER_LEN + 1); + } + /* + * get target name into recursive struct + */ + *colon = (int) nul_char; + rp->target = (wchar_t *) wsdup(line); + *bpatch = rp; + bpatch = &rp->next; + } + } + (void) fclose(fp); +} + +/* + * report_recursive_dep(target, line) + * + * Report a target as recursive. + * + * Parameters: + * line Dependency line reported + * + * Static variables used: + * bpatch Points to slot where next cell should be added + * changed Written if report set changed + */ +void +report_recursive_dep(Name target, wchar_t *line) +{ + Recursive_make rp; + wchar_t rec_buf[STRING_BUFFER_LENGTH]; + String_rec string; + + INIT_STRING_FROM_STACK(string, rec_buf); + cond_macros_into_string(target, &string); + /* + * find an applicable recursive entry, if there isn't one, create it + */ + rp = find_recursive_target(target); + if (rp == NULL) { + rp = ALLOC(Recursive_make); + (void) memset((char *) rp, 0, sizeof (Recursive_make_rec)); + wchar_t * wcb = get_wstring(target->string_mb); // XXX Tolik: needs retmem + rp->target = wcb; + rp->newline = (wchar_t *) wsdup(line); + rp->cond_macrostring = (wchar_t *) wsdup(rec_buf); + *bpatch = rp; + bpatch = &rp->next; + changed = true; + } else { + if ((rp->oldline != NULL) && !IS_WEQUAL(rp->oldline, line)) { + rp->newline = (wchar_t *) wsdup(line); + changed = true; + } + rp->removed = false; + } +} + +/* + * find_recursive_target(target) + * + * Search the list for a given target. + * + * Return value: + * The target cell + * + * Parameters: + * target The target we need + * top_level_target more info used to determinde the + * target we need + * + * Static variables used: + * recursive_list The list of targets + */ +Recursive_make +find_recursive_target(Name target) +{ + Recursive_make rp; + String_rec string; + wchar_t rec_buf[STRING_BUFFER_LENGTH]; + + INIT_STRING_FROM_STACK(string, rec_buf); + cond_macros_into_string(target, &string); + + Wstring tstr(target); + wchar_t * wcb = tstr.get_string(); + for (rp = recursive_list; rp != NULL; rp = rp->next) { + /* + * If this entry has already been removed, ignore it. + */ + if (rp->removed) + continue; + /* + * If this target, and the target on the list are the same + * and if one of them contains conditional macro info, while + * the other doesn't, remove this entry from the list of + * recursive entries. This can only happen if the Makefile + * has changed to no longer contain conditional macros. + */ + if (IS_WEQUAL(rp->target, wcb)) { + if (rp->cond_macrostring[VER_LEN] == '\0' && + string.buffer.start[VER_LEN] != '\0'){ + rp->removed = true; + continue; + } else if (rp->cond_macrostring[VER_LEN] != '\0' && + string.buffer.start[VER_LEN] == '\0'){ + rp->removed = true; + continue; + } + } + /* + * If this is not a VERS2 entry, only need to match + * the target name. toptarg information from VERS1 entries + * are ignored. + */ + MBSTOWCS(wcs_buffer, DEPINFO_FMT_VERSION); + if (IS_WEQUALN(wcs_buffer, string.buffer.start, VER_LEN)) { + if (IS_WEQUAL(rp->cond_macrostring, + string.buffer.start) && + IS_WEQUAL(rp->target, wcb)) { + return rp; + } + } else { + if (IS_WEQUAL(rp->target, wcb)) { + return rp; + } + } + } + return NULL; +} + +/* + * remove_recursive_dep(target, top_level_target) + * + * Mark a target as no longer recursive. + * + * Parameters: + * target The target we want to remove + * top_level_target target we want to remove must be built from + * the same top level target + * + * Static variables used: + * changed Written if report set changed + */ +void +remove_recursive_dep(Name target) +{ + Recursive_make rp; + + rp = find_recursive_target(target); + + if ( rp != NULL ) { + rp->removed = true; + changed = true; + if(rp->target) { + retmem(rp->target); + rp->target = NULL; + } + if(rp->newline) { + retmem(rp->newline); + rp->newline = NULL; + } + if(rp->oldline) { + retmem(rp->oldline); + rp->oldline = NULL; + } + if(rp->cond_macrostring) { + retmem(rp->cond_macrostring); + rp->cond_macrostring = NULL; + } + } +} + +#ifdef NSE +/* + * report_recursive_done() + * + * Write the .nse_depinfo file. + * + * Parameters: + * + * Static variables used: + * recursive_list The list of targets + * changed Written if report set changed + * + * Global variables used: + * recursive_name The Name ".RECURSIVE", compared against + */ +void +report_recursive_done(void) +{ + char *search_dir; + char nse_depinfo[MAXPATHLEN]; + char tmpfile[MAXPATHLEN]; + FILE *ofp; + FILE *ifp; + wchar_t *space; + wchar_t *data; + wchar_t *line; + wchar_t *bigger_line; + int line_size, line_index; + int lock_err; + Recursive_make rp; + + if (changed == false) { + return; + } + + search_dir = getenv(NOCATGETS("NSE_DEP")); + if (search_dir == NULL) { + return; + } + (void) sprintf(nse_depinfo, "%s/%s", search_dir, NSE_DEPINFO); + (void) sprintf(tmpfile, "%s.%d", nse_depinfo, getpid()); + ofp = fopen(tmpfile, "w"); + if (ofp == NULL) { + (void) fprintf(stderr, + catgets(catd, 1, 116, "Cannot open `%s' for writing\n"), + tmpfile); + return; + } + (void) sprintf(nse_depinfo_lockfile, + "%s/%s", search_dir, NSE_DEPINFO_LOCK); + if (lock_err = file_lock(nse_depinfo, + nse_depinfo_lockfile, + (int *) &nse_depinfo_locked, 0)) { + (void) fprintf(stderr, + catgets(catd, 1, 117, "writing .RECURSIVE lines to %s\n"), + tmpfile); + (void) fprintf(stderr, + catgets(catd, 1, 118, "To recover, merge .nse_depinfo.%d with .nse_depinfo\n"), + getpid(), + catgets(catd, 1, 119, "with .nse_depinfo")); + } + + if (nse_depinfo_locked) { + ifp = fopen(nse_depinfo, "r"); + if (ifp != NULL) { + /* + * Copy all the non-.RECURSIVE lines from + * the old file to the new one. + */ + line_size = MAXPATHLEN; + line_index = line_size - 1; + line = ALLOC_WC(line_size); + while (fgetws(line, line_size, ifp) != NULL) { + while (wslen(line) == line_index) { + if (line[wslen(line) - 1] == '\n') { + continue; + } + bigger_line = ALLOC_WC(2 * line_size); + wscpy(bigger_line, line); + retmem(line); + line = bigger_line; + if (fgetws(&line[line_index], + line_size, ifp) == NULL) + continue; + line_index = 2 * line_index; + line_size = 2 * line_size; + } + + space = wschr(line, (int) space_char); + if (space != NULL && + IS_WEQUALN(&space[1], + recursive_name->string, + (int) recursive_name->hash.length)) { + continue; + } + WCSTOMBS(mbs_buffer, line); + (void) fprintf(ofp, "%s", mbs_buffer); + } + (void) fclose(ifp); + } + } + + /* + * Write out the .RECURSIVE lines. + */ + for (rp = recursive_list; rp != NULL; rp = rp->next) { + if (rp->removed) { + continue; + } + if (rp->newline != NULL) { + data = rp->newline; + } else { + data = rp->oldline; + } + if (data != NULL) { + WCSTOMBS(mbs_buffer, data); + (void) fprintf(ofp, "%s\n", mbs_buffer); + } + } + (void) fclose(ofp); + + if (nse_depinfo_locked) { + (void) rename(tmpfile, nse_depinfo); + (void) unlink(nse_depinfo_lockfile); + nse_depinfo_locked = false; + nse_depinfo_lockfile[0] = '\0'; + (void) chmod(nse_depinfo, 0666); + } +} +#endif // NSE + +/* gather_recursive_deps() + * + * Create or update list of recursive targets. + */ +void +gather_recursive_deps(void) +{ + Name_set::iterator np, e; + String_rec rec; + wchar_t rec_buf[STRING_BUFFER_LENGTH]; + register Property lines; + Boolean has_recursive; + Dependency dp; + + report_recursive_init(); + + /* Go thru all targets and dump recursive dependencies */ + for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) { + if (np->has_recursive_dependency){ + has_recursive = false; + /* + * start .RECURSIVE line with target: + */ + INIT_STRING_FROM_STACK(rec, rec_buf); + APPEND_NAME(np, &rec, FIND_LENGTH); + append_char((int) colon_char, &rec); + append_char((int) space_char, &rec); + + for (lines = get_prop(np->prop,recursive_prop); + lines != NULL; + lines = get_prop(lines->next, recursive_prop)) { + /* + * if entry is already in depinfo + * file or entry was not built, ignore it + */ + if (lines->body.recursive.in_depinfo) + continue; + if (!lines->body.recursive.has_built) + continue; + has_recursive = true; + lines->body.recursive.in_depinfo=true; + + /* + * Write the remainder of the + * .RECURSIVE line + */ + APPEND_NAME(recursive_name, &rec, + FIND_LENGTH); + append_char((int) space_char, &rec); + APPEND_NAME(lines->body.recursive.directory, + &rec, FIND_LENGTH); + append_char((int) space_char, &rec); + APPEND_NAME(lines->body.recursive.target, + &rec, FIND_LENGTH); + append_char((int) space_char, &rec); + + /* Complete list of makefiles used */ + for (dp = lines->body.recursive.makefiles; + dp != NULL; + dp = dp->next) { + APPEND_NAME(dp->name, &rec, FIND_LENGTH); + append_char((int) space_char, &rec); + } + } + /* + * dump list of conditional targets, + * and report recursive entry, if needed + */ + cond_macros_into_string(np, &rec); + if (has_recursive){ + report_recursive_dep(np, rec.buffer.start); + } + + } else if ( np->has_built ) { + remove_recursive_dep(np); + } + } +} + diff --git a/usr/src/make_src/Make/bin/make/common/state.cc b/usr/src/make_src/Make/bin/make/common/state.cc new file mode 100644 index 0000000..eff066a --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/state.cc @@ -0,0 +1,463 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)state.cc 1.27 06/12/12 + */ + +#pragma ident "@(#)state.cc 1.27 06/12/12" + +/* + * state.c + * + * This file contains the routines that write the .make.state file + */ + +/* + * Included files + */ +#include <mk/defs.h> +#include <mksh/misc.h> /* errmsg() */ +#include <setjmp.h> /* setjmp() */ +#include <unistd.h> /* getpid() */ +#include <errno.h> /* errno */ +#include <locale.h> /* MB_CUR_MAX */ + +/* + * Defined macros + */ +#define LONGJUMP_VALUE 17 +#define XFWRITE(string, length, fd) {if (fwrite(string, 1, length, fd) == 0) \ + longjmp(long_jump, LONGJUMP_VALUE);} +#define XPUTC(ch, fd) { \ + if (putc((int) ch, fd) == EOF) \ + longjmp(long_jump, LONGJUMP_VALUE); \ + } +#define XFPUTS(string, fd) fputs(string, fd) + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +/* + * File table of contents + */ +static char * escape_target_name(Name np) +{ + if(np->dollar) { + int len = strlen(np->string_mb); + char * buff = (char*)malloc(2 * len); + int pos = 0; + wchar_t wc; + int pp = 0; + while(pos < len) { + int n = mbtowc(&wc, np->string_mb + pos, MB_CUR_MAX); + if(n < 0) { // error - this shouldn't happen + (void)free(buff); + return strdup(np->string_mb); + } + if(wc == dollar_char) { + buff[pp] = '\\'; pp++; + buff[pp] = '$'; pp++; + } else { + for(int j=0;j<n;j++) { + buff[pp] = np->string_mb[pos+j]; pp++; + } + } + pos += n; + } + buff[pp] = '\0'; + return buff; + } else { + return strdup(np->string_mb); + } +} + +static void print_auto_depes(register Dependency dependency, register FILE *fd, register Boolean built_this_run, register int *line_length, register char *target_name, jmp_buf long_jump); + +/* + * write_state_file(report_recursive, exiting) + * + * Write a new version of .make.state + * + * Parameters: + * report_recursive Should only be done at end of run + * exiting true if called from the exit handler + * + * Global variables used: + * built_last_make_run The Name ".BUILT_LAST_MAKE_RUN", written + * command_changed If no command changed we do not need to write + * current_make_version The Name "<current version>", written + * do_not_exec_rule If -n is on we do not write statefile + * hashtab The hashtable that contains all names + * keep_state If .KEEP_STATE is no on we do not write file + * make_state The Name ".make.state", used for opening file + * make_version The Name ".MAKE_VERSION", written + * recursive_name The Name ".RECURSIVE", written + * rewrite_statefile Indicates that something changed + */ + +void +#ifdef NSE +write_state_file(int report_recursive, Boolean exiting) +#else +write_state_file(int, Boolean exiting) +#endif +{ + register FILE *fd; + int lock_err; + char buffer[MAXPATHLEN]; + char make_state_tempfile[MAXPATHLEN]; + jmp_buf long_jump; + register int attempts = 0; + Name_set::iterator np, e; + register Property lines; + register int m; + Dependency dependency; + register Boolean name_printed; + Boolean built_this_run = false; + char *target_name; + int line_length; + register Cmd_line cp; + + + if (!rewrite_statefile || + !command_changed || + !keep_state || + do_not_exec_rule || + (report_dependencies_level > 0)) { + return; + } + /* Lock the file for writing. */ + make_state_lockfile = getmem(strlen(make_state->string_mb) + strlen(NOCATGETS(".lock")) + 1); + (void) sprintf(make_state_lockfile, + NOCATGETS("%s.lock"), + make_state->string_mb); + if (lock_err = file_lock(make_state->string_mb, + make_state_lockfile, + (int *) &make_state_locked, 0)) { + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + + /* + * We need to make sure that we are not being + * called by the exit handler so we don't call + * it again. + */ + + if (exiting) { + (void) sprintf(buffer, NOCATGETS("%s/.make.state.%d.XXXXXX"), tmpdir, getpid()); + report_pwd = true; + warning(catgets(catd, 1, 60, "Writing to %s"), buffer); + int fdes = mkstemp(buffer); + if ((fdes < 0) || (fd = fdopen(fdes, "w")) == NULL) { + fprintf(stderr, + catgets(catd, 1, 61, "Could not open statefile `%s': %s"), + buffer, + errmsg(errno)); + return; + } + } else { + report_pwd = true; + fatal(catgets(catd, 1, 62, "Can't lock .make.state")); + } + } + + (void) sprintf(make_state_tempfile, + NOCATGETS("%s.tmp"), + make_state->string_mb); + /* Delete old temporary statefile (in case it exists) */ + (void) unlink(make_state_tempfile); + if ((fd = fopen(make_state_tempfile, "w")) == NULL) { + lock_err = errno; /* Save it! unlink() can change errno */ + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + fatal(catgets(catd, 1, 59, "Could not open temporary statefile `%s': %s"), + make_state_tempfile, + errmsg(lock_err)); + } +#ifdef NSE + if (nse) { + (void) fchmod(fileno(fd), 0666); + } +#endif + /* + * Set a trap for failed writes. If a write fails, the routine + * will try saving the .make.state file under another name in /tmp. + */ + if (setjmp(long_jump)) { + (void) fclose(fd); + if (attempts++ > 5) { + if ((make_state_lockfile != NULL) && + make_state_locked) { + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } + fatal(catgets(catd, 1, 63, "Giving up on writing statefile")); + } + sleep(10); + (void) sprintf(buffer, NOCATGETS("%s/.make.state.%d.XXXXXX"), tmpdir, getpid()); + int fdes = mkstemp(buffer); + if ((fdes < 0) || (fd = fdopen(fdes, "w")) == NULL) { + fatal(catgets(catd, 1, 64, "Could not open statefile `%s': %s"), + buffer, + errmsg(errno)); + } + warning(catgets(catd, 1, 65, "Initial write of statefile failed. Trying again on %s"), + buffer); + } + + /* Write the version stamp. */ + XFWRITE(make_version->string_mb, + strlen(make_version->string_mb), + fd); + XPUTC(colon_char, fd); + XPUTC(tab_char, fd); + XFWRITE(current_make_version->string_mb, + strlen(current_make_version->string_mb), + fd); + XPUTC(newline_char, fd); + + /* + * Go through all the targets, dump their dependencies and + * command used. + */ + for (np = hashtab.begin(), e = hashtab.end(); np != e; np++) { + /* + * If the target has no command used nor dependencies, + * we can go to the next one. + */ + if ((lines = get_prop(np->prop, line_prop)) == NULL) { + continue; + } + /* If this target is a special target, don't print. */ + if (np->special_reader != no_special) { + continue; + } + /* + * Find out if any of the targets dependencies should + * be written to .make.state. + */ + for (m = 0, dependency = lines->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + if (m = !dependency->stale + && (dependency->name != force) +#ifndef PRINT_EXPLICIT_DEPEN + && dependency->automatic +#endif + ) { + break; + } + } + /* Only print if dependencies listed. */ + if (m || (lines->body.line.command_used != NULL)) { + name_printed = false; + /* + * If this target was built during this make run, + * we mark it. + */ + built_this_run = false; + if (np->has_built) { + built_this_run = true; + XFWRITE(built_last_make_run->string_mb, + strlen(built_last_make_run->string_mb), + fd); + XPUTC(colon_char, fd); + XPUTC(newline_char, fd); + } + /* If the target has dependencies, we dump them. */ + target_name = escape_target_name(np); + if (np->has_long_member_name) { + target_name = + get_prop(np->prop, long_member_name_prop) + ->body.long_member_name.member_name-> + string_mb; + } + if (m) { + XFPUTS(target_name, fd); + XPUTC(colon_char, fd); + XFPUTS("\t", fd); + name_printed = true; + line_length = 0; + for (dependency = + lines->body.line.dependencies; + dependency != NULL; + dependency = dependency->next) { + print_auto_depes(dependency, + fd, + built_this_run, + &line_length, + target_name, + long_jump); + } + XFPUTS("\n", fd); + } + /* If there is a command used, we dump it. */ + if (lines->body.line.command_used != NULL) { + /* + * Only write the target name if it + * wasn't done for the dependencies. + */ + if (!name_printed) { + XFPUTS(target_name, fd); + XPUTC(colon_char, fd); + XPUTC(newline_char, fd); + } + /* + * Write the command lines. + * Prefix each textual line with a tab. + */ + for (cp = lines->body.line.command_used; + cp != NULL; + cp = cp->next) { + char *csp; + int n; + + XPUTC(tab_char, fd); + if (cp->command_line != NULL) { + for (csp = cp-> + command_line-> + string_mb, + n = strlen(cp-> + command_line-> + string_mb); + n > 0; + n--, csp++) { + XPUTC(*csp, fd); + if (*csp == + (int) newline_char) { + XPUTC(tab_char, + fd); + } + } + } + XPUTC(newline_char, fd); + } + } + (void)free(target_name); + } + } + if (fclose(fd) == EOF) { + longjmp(long_jump, LONGJUMP_VALUE); + } + if (attempts == 0) { + if (unlink(make_state->string_mb) != 0 && errno != ENOENT) { + lock_err = errno; /* Save it! unlink() can change errno */ + /* Delete temporary statefile */ + (void) unlink(make_state_tempfile); + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + fatal(catgets(catd, 1, 356, "Could not delete old statefile `%s': %s"), + make_state->string_mb, + errmsg(lock_err)); + } + if (rename(make_state_tempfile, make_state->string_mb) != 0) { + lock_err = errno; /* Save it! unlink() can change errno */ + /* Delete temporary statefile */ + (void) unlink(make_state_tempfile); + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + fatal(catgets(catd, 1, 357, "Could not rename `%s' to `%s': %s"), + make_state_tempfile, + make_state->string_mb, + errmsg(lock_err)); + } + } + if ((make_state_lockfile != NULL) && make_state_locked) { + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } +#ifdef NSE + if (report_recursive) { + report_recursive_done(); + } +#endif +} + +/* + * print_auto_depes(dependency, fd, built_this_run, + * line_length, target_name, long_jump) + * + * Will print a dependency list for automatic entries. + * + * Parameters: + * dependency The dependency to print + * fd The file to print it to + * built_this_run If on we prefix each line with .BUILT_THIS... + * line_length Pointer to line length var that we update + * target_name We need this when we restart line + * long_jump setjmp/longjmp buffer used for IO error action + * + * Global variables used: + * built_last_make_run The Name ".BUILT_LAST_MAKE_RUN", written + * force The Name " FORCE", compared against + */ +static void +print_auto_depes(register Dependency dependency, register FILE *fd, register Boolean built_this_run, register int *line_length, register char *target_name, jmp_buf long_jump) +{ + if (!dependency->automatic || + dependency->stale || + (dependency->name == force)) { + return; + } + XFWRITE(dependency->name->string_mb, + strlen(dependency->name->string_mb), + fd); + /* + * Check if the dependency line is too long. + * If so, break it and start a new one. + */ + if ((*line_length += (int) strlen(dependency->name->string_mb) + 1) > 450) { + *line_length = 0; + XPUTC(newline_char, fd); + if (built_this_run) { + XFPUTS(built_last_make_run->string_mb, fd); + XPUTC(colon_char, fd); + XPUTC(newline_char, fd); + } + XFPUTS(target_name, fd); + XPUTC(colon_char, fd); + XPUTC(tab_char, fd); + } else { + XFPUTS(" ", fd); + } + return; +} + + diff --git a/usr/src/make_src/Make/bin/make/common/svr4.make.rules.file b/usr/src/make_src/Make/bin/make/common/svr4.make.rules.file new file mode 100644 index 0000000..55c9a1d --- /dev/null +++ b/usr/src/make_src/Make/bin/make/common/svr4.make.rules.file @@ -0,0 +1,242 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1994 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)svr4.make.rules.file 1.4 06/12/12 +# +.SUFFIXES: .o .c .c~ .y .y~ .l .l~ .s .s~ .sh .sh~ .h .h~ .f .f~ \ +.C .C~ .Y .Y~ .L .L~ + +MAKE=make +BUILD=build +AR=ar +ARFLAGS=rv +AS=as +ASFLAGS= +CC=cc +CFLAGS=-O +F77=f77 +FFLAGS=-O +GET=get +GFLAGS= +LD=ld +LDFLAGS= +LEX=lex +LFLAGS= +YACC=yacc +YFLAGS= +C++C=CC +C++FLAGS=-O + + +.c: + $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) +.c~: + $(GET) $(GFLAGS) $< + $(CC) $(CFLAGS) $*.c -o $@ $(LDFLAGS) + -rm -f $*.c +.f: + $(F77) $(FFLAGS) $< -o $@ $(LDFLAGS) +.f~: + $(GET) $(GFLAGS) $< + $(F77) $(FFLAGS) $*.f -o $@ $(LDFLAGS) + -rm -f $*.f +.s: + $(AS) $(ASFLAGS) $< -o $@ $(LDFLAGS) +.s~: + $(GET) $(GFLAGS) $< + $(AS) $(ASFLAGS) $*.s -o $* $(LDFLAGS) + -rm -f $*.s +.sh: + cp $< $@; chmod 0777 $@ +.sh~: + $(GET) $(GFLAGS) $< + cp $*.sh $*; chmod 0777 $@ + -rm -f $*.sh +.C: + $(C++C) $(C++FLAGS) $< -o $@ $(LDFLAGS) +.C~: + $(GET) $(GFLAGS) $< + $(C++C) $(C++FLAGS) $*.C -o $@ $(LDFLAGS) + -rm -f $*.C + +.c.a: + $(CC) $(CFLAGS) -c $< + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.o +.c.o: + $(CC) $(CFLAGS) -c $< +.c~.a: + $(GET) $(GFLAGS) $< + $(CC) $(CFLAGS) -c $*.c + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.[co] +.c~.c: + $(GET) $(GFLAGS) $< +.c~.o: + $(GET) $(GFLAGS) $< + $(CC) $(CFLAGS) -c $*.c + -rm -f $*.c +.f.a: + $(F77) $(FFLAGS) -c $*.f + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.o +.f.o: + $(F77) $(FFLAGS) -c $*.f +.f~.a: + $(GET) $(GFLAGS) $< + $(F77) $(FFLAGS) -c $*.f + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.[fo] +.f~.f: + $(GET) $(GFLAGS) $< +.f~.o: + $(GET) $(GFLAGS) $< + $(F77) $(FFLAGS) -c $*.f + -rm -f $*.f +.h~.h: + $(GET) $(GFLAGS) $< +.l.c: + $(LEX) $(LFLAGS) $< + mv lex.yy.c $@ +.l.o: + $(LEX) $(LFLAGS) $< + $(CC) $(CFLAGS) -c lex.yy.c + -rm lex.yy.c; mv lex.yy.o $@ +.l~.c: + $(GET) $(GFLAGS) $< + $(LEX) $(LFLAGS) $*.l + mv lex.yy.c $@ + -rm -f $*.l +.l~.l: + $(GET) $(GFLAGS) $< +.l~.o: + $(GET) $(GFLAGS) $< + $(LEX) $(LFLAGS) $*.l + $(CC) $(CFLAGS) -c lex.yy.c + -rm -f lex.yy.c $*.l + mv lex.yy.o $@ +.s.a: + $(AS) $(ASFLAGS) -o $*.o $*.s + $(AR) $(ARFLAGS) $@ $*.o +.s.o: + $(AS) $(ASFLAGS) -o $@ $< +.s~.a: + $(GET) $(GFLAGS) $< + $(AS) $(ASFLAGS) -o $*.o $*.s + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.[so] +.s~.o: + $(GET) $(GFLAGS) $< + $(AS) $(ASFLAGS) -o $*.o $*.s + -rm -f $*.s +.s~.s: + $(GET) $(GFLAGS) $< +.sh~.sh: + $(GET) $(GFLAGS) $< +.y.c: + $(YACC) $(YFLAGS) $< + mv y.tab.c $@ +.y.o: + $(YACC) $(YFLAGS) $< + $(CC) $(CFLAGS) -c y.tab.c + -rm y.tab.c + mv y.tab.o $@ +.y~.c: + $(GET) $(GFLAGS) $< + $(YACC) $(YFLAGS) $*.y + mv y.tab.c $*.c + -rm -f $*.y +.y~.o: + $(GET) $(GFLAGS) $< + $(YACC) $(YFLAGS) $*.y + $(CC) $(CFLAGS) -c y.tab.c + -rm -f y.tab.c $*.y + mv y.tab.o $*.o +.y~.y : + $(GET) $(GFLAGS) $< +.C.a: + $(C++C) $(C++FLAGS) -c $< + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.o +.C.o: + $(C++C) $(C++FLAGS) -c $< +.C~.a: + $(GET) $(GFLAGS) $< + $(C++C) $(C++FLAGS) -c $*.C + $(AR) $(ARFLAGS) $@ $*.o + -rm -f $*.[Co] +.C~.C: + $(GET) $(GFLAGS) $< +.C~.o: + $(GET) $(GFLAGS) $< + $(C++C) $(C++FLAGS) -c $*.C + -rm -f $*.C +.L.C: + $(LEX) $(LFLAGS) $< + mv lex.yy.c $@ +.L.o: + $(LEX) $(LFLAGS) $< + $(C++C) $(C++FLAGS) -c lex.yy.c + -rm lex.yy.c; mv lex.yy.o $@ +.L~.C: + $(GET) $(GFLAGS) $< + $(LEX) $(LFLAGS) $*.L + mv lex.yy.c $@ + -rm -f $*.L +.L~.L: + $(GET) $(GFLAGS) $< +.L~.o: + $(GET) $(GFLAGS) $< + $(LEX) $(LFLAGS) $*.L + $(C++C) $(C++FLAGS) -c lex.yy.c + -rm -f lex.yy.c $*.L + mv lex.yy.c $@ +.Y.C: + $(YACC) $(YFLAGS) $< + mv y.tab.c $@ +.Y.o: + $(YACC) $(YFLAGS) $< + $(C++C) $(C++FLAGS) -c y.tab.c + -rm y.tab.c + mv y.tab.o $@ +.Y~.C: + $(GET) $(GFLAGS) $< + $(YACC) $(YFLAGS) $*.Y + mv y.tab.c $*.C + -rm -f $*.Y +.Y~.o: + $(GET) $(GFLAGS) $< + $(YACC) $(YFLAGS) $*.Y + $(C++C) $(C++FLAGS) -c y.tab.c + -rm -f y.tab.c $*.Y + mv y.tab.o $*.o +.Y~.Y : + $(GET) $(GFLAGS) $< + +markfile.o: markfile + echo "static char _sccsid[] = \"`grep @'(#)' markfile`\";" > markfile.c + $(CC) -c markfile.c + -rm -f markfile.c + +.SCCS_GET: + $(GET) $(GFLAGS) s.$@ diff --git a/usr/src/make_src/Make/bin/make/make.svr4/Makefile b/usr/src/make_src/Make/bin/make/make.svr4/Makefile new file mode 100644 index 0000000..96000a3 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/make.svr4/Makefile @@ -0,0 +1,38 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2001 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.6 06/12/12 +# + +TOP=../../../.. +include $(TOP)/rules/master.mk + +all clean clobber l10n_install: + +install: + $(INSTALL) -d $(DESTDIR)/usr/lib + $(INSTALL) -d $(DESTDIR)/usr/ccs/lib + rm -f $(DESTDIR)/usr/lib/svr4.make + rm -f $(DESTDIR)/usr/ccs/lib/svr4.make + ln $(DESTDIR)/usr/ccs/bin/make $(DESTDIR)/usr/lib/svr4.make + (cd $(DESTDIR)/usr/ccs/lib; ln -s ../../lib/svr4.make svr4.make) diff --git a/usr/src/make_src/Make/bin/make/make.xpg4/Makefile b/usr/src/make_src/Make/bin/make/make.xpg4/Makefile new file mode 100644 index 0000000..6688c9d --- /dev/null +++ b/usr/src/make_src/Make/bin/make/make.xpg4/Makefile @@ -0,0 +1,36 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.2 06/12/12 +# +# @(#)Makefile 1.1 95/06/29 SMI + +TOP=../../../.. +include $(TOP)/rules/master.mk + +all clean clobber l10n_install: + +install: + $(INSTALL) -d $(DESTDIR)/usr/xpg4/bin + rm -f $(DESTDIR)/usr/xpg4/bin/make + ln $(DESTDIR)/usr/ccs/bin/make $(DESTDIR)/usr/xpg4/bin/make diff --git a/usr/src/make_src/Make/bin/make/smake/Makefile b/usr/src/make_src/Make/bin/make/smake/Makefile new file mode 100644 index 0000000..0cf0d68 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/smake/Makefile @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.5 06/12/12 +# + +TOP = ../../../.. +include $(TOP)/rules/variant.mk +include $(TOP)/rules/derived.mk + diff --git a/usr/src/make_src/Make/bin/make/smake/src/Makefile b/usr/src/make_src/Make/bin/make/smake/src/Makefile new file mode 100644 index 0000000..bdefefc --- /dev/null +++ b/usr/src/make_src/Make/bin/make/smake/src/Makefile @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.3 06/12/12 +# + +# Generic makefile for use in src directories. Knows how to make common things +# in the right $(VARIANT) directory. + +#TOP = ../../../../.. +include $(TOP)/rules/variant.mk + +all := TARG = all +install := TARG = install +clean := TARG = clean +test := TARG = test +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +SRC = ../src +MFLAGS += SRC=$(SRC) + +# See $(TOP)/rules/master.mk for how these are built. +%.h %.cc %.C %.E %.o all install clean test l10n_install i18n_install: FRC + @ if [ ! -d ../$(VARIANT) ]; then \ + mkdir ../$(VARIANT) ; \ + fi + cd ../$(VARIANT); $(MAKE) $(MFLAGS) -f $(SRC)/Variant.mk DESTDIR=$(DESTDIR) $@ + +FRC: diff --git a/usr/src/make_src/Make/bin/make/smake/src/Variant.mk b/usr/src/make_src/Make/bin/make/smake/src/Variant.mk new file mode 100644 index 0000000..c2e5f64 --- /dev/null +++ b/usr/src/make_src/Make/bin/make/smake/src/Variant.mk @@ -0,0 +1,155 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Variant.mk 1.36 06/12/12 +# + +TOP = ../../../../.. +include $(TOP)/rules/master.mk +include $(TOP)/Make/lib/Lib.mk + +# RELEASE_VER should be "Generic" for FCS. Otherwise it should be overridden +# to display build number - "Build XX", patch number - "Patch XXXXXX-XX", etc. + +PKG_TOP = ../../../.. +PROG = make +PACKAGE = SUNWspro +PRODVER = 11 +PRODVER_V = SunOS 5.11 +RELEASE_VER = Generic +DATE:sh = date '+%B %Y' + +VERSTRING = RELEASE VERSION $(PRODVER_V) $(RELEASE_VER) $(DATE) + +MORE_SRC = \ + ar.cc \ + depvar.cc \ + doname.cc \ + dosys.cc \ + files.cc \ + globals.cc \ + implicit.cc \ + macro.cc \ + main.cc \ + misc.cc \ + nse_printdep.cc \ + read.cc \ + read2.cc \ + rep.cc \ + state.cc + +CPPFLAGS += -I$(PKG_TOP)/include + +LDLIB += \ + -lnsl \ + -lsocket \ + -lw + +HDRS_DIR = $(PKG_TOP)/include/mk +HDRS_LIST = $(HDRS_DIR)/copyright.h $(HDRS_DIR)/defs.h + +.INIT: $(HDRS_LIST) + +SRCS = $(PROG).cc $(MORE_SRC) +OBJS = $(SRCS:%.cc=%.o) + +LIB += -lintl -lm + +all install:: $(PROG) + +$(PROG): $(OBJS) + $(CCC) $(CCFLAGS) $(LDFLAGS) -o $@ \ + $(OBJS) $(LIB) $(I18LIB) $(LDLIB) + /bin/sh $(TOP)/exe/sanity-check.sh $(TOP) $(PROG) + +clean: + $(RM) $(OBJS) $(PROG) + + +include $(TOP)/rules/computed-options.mk + +# +# This LIB macro must be declared after the include's above +# +LIB = \ + $(LIBMKSH) \ + $(LIBMKSDMSI18N) \ + $(LIBBSD) \ + $(LIBVROOT) + +%.o: ../../common/%.cc + $(COMPILE.cc) $(OUTPUT_OPTION) $< + +depvar.o nse.o nse_printdep.o := CPPFLAGS += -DSUNOS4_AND_AFTER + +LDFLAGS += -xildoff -norunpath + +install:: install-make-hdrs install-make-bin + +IHDR = make.rules.file +VIHDR = svr4.make.rules.file +HDR = ${PKG_TOP}/bin/make/common/make.rules.file +VHDR = ${PKG_TOP}/bin/make/common/svr4.make.rules.file +HDRSDIR = $(DESTDIR)/usr/share/lib/make +HDRFILE = make.rules +VHDRFILE = svr4.make.rules +SMAKEDIR = $(DESTDIR)/usr/ccs/bin + +install-make-bin: make + $(INSTALL) -d $(SMAKEDIR) + $(INSTALL) make $(SMAKEDIR) + mcs -d $(SMAKEDIR)/make + mcs -a '@(#)$(VERSTRING)' $(SMAKEDIR)/make + +install-make-hdrs: $(HDR) $(VHDR) + $(INSTALL) -d $(HDRSDIR) + $(INSTALL) -m 0444 $(HDR) $(HDRSDIR) + mv -f $(HDRSDIR)/$(IHDR) $(HDRSDIR)/$(HDRFILE) + $(INSTALL) -m 0444 $(VHDR) $(HDRSDIR) + mv -f $(HDRSDIR)/$(VIHDR) $(HDRSDIR)/$(VHDRFILE) + + +# +# i18n stuff +# +MAKE_MSG = SUNW_SPRO_MAKE.msg +#I18N_DIRS = ../../common ../../../../lib/bsd/src ../../../../lib/mksh/src ../../../../lib/vroot/src +I18N_DIRS = ../../common +TEXTDOMAIN = SUNW_SPRO_MAKE +APPPATH = $(PKG_TOP)/bin/make/smake/$(VARIANT) +LIB_DESTDIR = $(DESTDIR)/usr/lib +CAT_DESTDIR = $(LIB_DESTDIR)/locale/C/LC_MESSAGES + +$(CAT_DESTDIR): + $(INSTALL) -d $@ + +msg_catalogs: $(CAT_DESTDIR) .WAIT MAKE_MSG + cp $(APPPATH)/$(TEXTDOMAIN).msg $(CAT_DESTDIR) + +MAKE_MSG: + $(GENMSG) -l $(SRC)/genmsg.project -o $(TEXTDOMAIN).msg `find $(I18N_DIRS) \( -name '*.cc' -o -name '*.c' -o -name '*.y' -o -name '*.h' \) -print | grep -v /SCCS/` + rm -f *.cc.new + +i18n_install: msg_catalogs + +FRC: diff --git a/usr/src/make_src/Make/include/bsd/bsd.h b/usr/src/make_src/Make/include/bsd/bsd.h new file mode 100644 index 0000000..c8b9cb6 --- /dev/null +++ b/usr/src/make_src/Make/include/bsd/bsd.h @@ -0,0 +1,58 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)bsd.h 1.6 06/12/12 + */ + +#pragma ident "@(#)bsd.h 1.6 06/12/12" + +/* + * bsd/bsd.h: Interface definitions to BSD compatibility functions for SVR4. + */ + +#ifndef _BSD_BSD_H +#define _BSD_BSD_H + +#include <signal.h> + +#if defined (HP_UX) || defined (linux) +typedef void SIG_FUNC_TYP(int); +typedef SIG_FUNC_TYP *SIG_TYP; +#define SIG_PF SIG_TYP +#endif + +#ifndef __cplusplus +typedef void (*SIG_PF) (int); +#endif + +#ifdef __cplusplus +extern "C" SIG_PF bsd_signal(int a, SIG_PF b); +#else +extern void (*bsd_signal(int, void (*) (int))) (int); +#endif +extern void bsd_signals(void); + +#endif + diff --git a/usr/src/make_src/Make/include/mk/copyright.h b/usr/src/make_src/Make/include/mk/copyright.h new file mode 100644 index 0000000..1d04701 --- /dev/null +++ b/usr/src/make_src/Make/include/mk/copyright.h @@ -0,0 +1,27 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)copyright.h 1.11 06/12/12 + */ diff --git a/usr/src/make_src/Make/include/mk/defs.h b/usr/src/make_src/Make/include/mk/defs.h new file mode 100644 index 0000000..53510a2 --- /dev/null +++ b/usr/src/make_src/Make/include/mk/defs.h @@ -0,0 +1,495 @@ +#ifndef _MK_DEFS_H +#define _MK_DEFS_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)defs.h 1.61 06/12/12 + */ + +#pragma ident "@(#)defs.h 1.61 06/12/12" + +/* + * Included files + */ +#ifdef DISTRIBUTED +# include <dm/Avo_AcknowledgeMsg.h> +# include <dm/Avo_DoJobMsg.h> +# include <dm/Avo_JobResultMsg.h> +#endif + +#include <mksh/defs.h> + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +# include <rw/xdrstrea.h> +#endif + + +/* + * Defined macros + */ + +#define SKIPSPACE(x) while (*x && \ + ((*x == (int) space_char) || \ + (*x == (int) tab_char) || \ + (*x == (int) comma_char))) { \ + x++; \ + } + +#define SKIPWORD(x) while (*x && \ + (*x != (int) space_char) && \ + (*x != (int) tab_char) && \ + (*x != (int) newline_char) && \ + (*x != (int) comma_char) && \ + (*x != (int) equal_char)) { \ + x++; \ + } + +#define SKIPTOEND(x) while (*x && \ + (*x != (int) newline_char)) { \ + x++; \ + } + +#define PMAKE_DEF_MAX_JOBS 2 /* Default number of parallel jobs. */ + +#define OUT_OF_DATE(a,b) \ + (((a) < (b)) || (((a) == file_doesnt_exist) && ((b) == file_doesnt_exist))) + +#define OUT_OF_DATE_SEC(a,b) \ + (((a).tv_sec < (b).tv_sec) || (((a).tv_sec == file_doesnt_exist.tv_sec) && ((b).tv_sec == file_doesnt_exist.tv_sec))) + +#define SETVAR(name, value, append) \ + setvar_daemon(name, value, append, no_daemon, \ + true, debug_level) +#ifdef SUN5_0 +#define MAX(a,b) (((a)>(b))?(a):(b)) +/* + * New feature added to SUN5_0 make, invoke the vanilla svr4 make when + * the USE_SVR4_MAKE environment variable is set. + */ +#define SVR4_MAKE "/usr/ccs/lib/svr4.make" +#define USE_SVR4_MAKE "USE_SVR4_MAKE" +#endif +/* + * The standard MAXHOSTNAMELEN is 64. We want 32. + */ +#define MAX_HOSTNAMELEN 32 + + +/* + * typedefs & structs + */ +typedef enum { + no_state, + scan_name_state, + scan_command_state, + enter_dependencies_state, + enter_conditional_state, + enter_equal_state, + illegal_bytes_state, + illegal_eoln_state, + poorly_formed_macro_state, + exit_state +} Reader_state; + +struct _Name_vector { + struct _Name *names[64]; + struct _Chain *target_group[64]; + short used; + struct _Name_vector *next; +}; + +struct _Running { + struct _Running *next; + Doname state; + struct _Name *target; + struct _Name *true_target; + struct _Property *command; + struct _Name *sprodep_value; + char *sprodep_env; + int recursion_level; + Boolean do_get; + Boolean implicit; + Boolean redo; + int auto_count; + struct _Name **automatics; + pid_t pid; +#ifdef TEAMWARE_MAKE_CMN + int job_msg_id; +#else + int host; +#endif + char *stdout_file; + char *stderr_file; + struct _Name *temp_file; + int conditional_cnt; + struct _Name **conditional_targets; +#ifdef TEAMWARE_MAKE_CMN + Boolean make_refd; +#endif +}; + +typedef enum { + serial_mode, + parallel_mode, + distributed_mode +} DMake_mode; + +typedef enum { + txt1_mode, + txt2_mode, + html1_mode +} DMake_output_mode; + +struct _Recursive_make { + struct _Recursive_make *next; /* Linked list */ + wchar_t *target;/* Name of target */ + wchar_t *oldline;/* Original line in .nse_depinfo */ + wchar_t *newline;/* New line in .nse_depinfo */ + wchar_t *cond_macrostring; + /* string built from value of + * conditional macros used by + * this target + */ + Boolean removed;/* This target is no longer recursive*/ +}; + +struct _Dyntarget { + struct _Dyntarget *next; + struct _Name *name; +}; + + +/* + * Typedefs for all structs + */ +typedef struct _Cmd_line *Cmd_line, Cmd_line_rec; +typedef struct _Dependency *Dependency, Dependency_rec; +typedef struct _Macro *Macro, Macro_rec; +typedef struct _Name_vector *Name_vector, Name_vector_rec; +typedef struct _Percent *Percent, Percent_rec; +typedef struct _Dyntarget *Dyntarget; +typedef struct _Recursive_make *Recursive_make, Recursive_make_rec; +typedef struct _Running *Running, Running_rec; + + +/* + * extern declarations for all global variables. + * The actual declarations are in globals.cc + */ +extern Boolean allrules_read; +extern Name posix_name; +extern Name svr4_name; +extern Boolean sdot_target; +extern Boolean all_parallel; +extern Boolean assign_done; +extern Boolean build_failed_seen; +#ifdef DISTRIBUTED +extern Boolean building_serial; +#endif +extern Name built_last_make_run; +extern Name c_at; +#ifdef DISTRIBUTED +extern Boolean called_make; +#endif +extern Boolean command_changed; +extern Boolean commands_done; +extern Chain conditional_targets; +extern Name conditionals; +extern Boolean continue_after_error; +extern Property current_line; +extern Name current_make_version; +extern Name current_target; +extern short debug_level; +extern Cmd_line default_rule; +extern Name default_rule_name; +extern Name default_target_to_build; +extern Boolean depinfo_already_read; +extern Name dmake_group; +extern Name dmake_max_jobs; +extern Name dmake_mode; +extern DMake_mode dmake_mode_type; +extern Name dmake_output_mode; +extern DMake_output_mode output_mode; +extern Name dmake_odir; +extern Name dmake_rcfile; +extern Name done; +extern Name dot; +extern Name dot_keep_state; +extern Name dot_keep_state_file; +extern Name empty_name; +extern Boolean fatal_in_progress; +extern int file_number; +extern Name force; +extern Name ignore_name; +extern Boolean ignore_errors; +extern Boolean ignore_errors_all; +extern Name init; +extern int job_msg_id; +extern Boolean keep_state; +extern Name make_state; +#ifdef TEAMWARE_MAKE_CMN +extern timestruc_t make_state_before; +#endif +extern Boolean make_state_locked; +extern Dependency makefiles_used; +extern Name makeflags; +extern Name make_version; +extern char mbs_buffer2[]; +extern char *mbs_ptr; +extern char *mbs_ptr2; +extern Boolean no_action_was_taken; +extern int mtool_msgs_fd; +extern Boolean no_parallel; +#ifdef SGE_SUPPORT +extern Boolean grid; +#endif +extern Name no_parallel_name; +extern Name not_auto; +extern Boolean only_parallel; +extern Boolean parallel; +extern Name parallel_name; +extern Name localhost_name; +extern int parallel_process_cnt; +extern Percent percent_list; +extern Dyntarget dyntarget_list; +extern Name plus; +extern Name pmake_machinesfile; +extern Name precious; +extern Name primary_makefile; +extern Boolean quest; +extern short read_trace_level; +extern Boolean reading_dependencies; +extern int recursion_level; +extern Name recursive_name; +extern short report_dependencies_level; +extern Boolean report_pwd; +extern Boolean rewrite_statefile; +extern Running running_list; +extern char *sccs_dir_path; +extern Name sccs_get_name; +extern Name sccs_get_posix_name; +extern Cmd_line sccs_get_rule; +extern Cmd_line sccs_get_org_rule; +extern Cmd_line sccs_get_posix_rule; +extern Name get_name; +extern Name get_posix_name; +extern Cmd_line get_rule; +extern Cmd_line get_posix_rule; +extern Boolean send_mtool_msgs; +extern Boolean all_precious; +extern Boolean report_cwd; +extern Boolean silent_all; +extern Boolean silent; +extern Name silent_name; +extern char *stderr_file; +extern char *stdout_file; +#ifdef SGE_SUPPORT +extern char script_file[]; +#endif +extern Boolean stdout_stderr_same; +extern Dependency suffixes; +extern Name suffixes_name; +extern Name sunpro_dependencies; +extern Boolean target_variants; +extern char *tmpdir; +extern char *temp_file_directory; +extern Name temp_file_name; +extern short temp_file_number; +extern wchar_t *top_level_target; +extern Boolean touch; +extern Boolean trace_reader; +extern Boolean build_unconditional; +extern pathpt vroot_path; +extern Name wait_name; +extern wchar_t wcs_buffer2[]; +extern wchar_t *wcs_ptr; +extern wchar_t *wcs_ptr2; +extern nl_catd catd; +extern long int hostid; + +/* + * Declarations of system defined variables + */ +#if !defined(linux) +/* On linux this variable is defined in 'signal.h' */ +extern char *sys_siglist[]; +#endif + +/* + * Declarations of system supplied functions + */ +extern int file_lock(char *, char *, int *, int); + +/* + * Declarations of functions declared and used by make + */ +extern void add_pending(Name target, int recursion_level, Boolean do_get, Boolean implicit, Boolean redo); +extern void add_running(Name target, Name true_target, Property command, int recursion_level, int auto_count, Name *automatics, Boolean do_get, Boolean implicit); +extern void add_serial(Name target, int recursion_level, Boolean do_get, Boolean implicit); +extern void add_subtree(Name target, int recursion_level, Boolean do_get, Boolean implicit); +extern void append_or_replace_macro_in_dyn_array(ASCII_Dyn_Array *Ar, char *macro); +#ifdef DISTRIBUTED +extern Doname await_dist(Boolean waitflg); +#endif +#ifdef TEAMWARE_MAKE_CMN +extern void await_parallel(Boolean waitflg); +#endif +extern void build_suffix_list(Name target_suffix); +extern Boolean check_auto_dependencies(Name target, int auto_count, Name *automatics); +extern void check_state(Name temp_file_name); +extern void cond_macros_into_string(Name np, String_rec *buffer); +extern void construct_target_string(); +extern void create_xdrs_ptr(void); +extern void depvar_add_to_list (Name name, Boolean cmdline); +#ifdef DISTRIBUTED +extern void distribute_rxm(Avo_DoJobMsg *dmake_job_msg); +extern int getRxmMessage(void); +extern Avo_JobResultMsg* getJobResultMsg(void); +extern Avo_AcknowledgeMsg* getAcknowledgeMsg(void); +#endif +extern Doname doname(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic = false); +extern Doname doname_check(register Name target, register Boolean do_get, register Boolean implicit, register Boolean automatic); +extern Doname doname_parallel(Name target, Boolean do_get, Boolean implicit); +extern Doname dosys(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err); +extern void dump_make_state(void); +extern void dump_target_list(void); +extern void enter_conditional(register Name target, Name name, Name value, register Boolean append); +extern void enter_dependencies(register Name target, Chain target_group, register Name_vector depes, register Cmd_line command, register Separator separator); +extern void enter_dependency(Property line, register Name depe, Boolean automatic); +extern void enter_equal(Name name, Name value, register Boolean append); +extern Percent enter_percent(register Name target, Chain target_group, register Name_vector depes, Cmd_line command); +extern Dyntarget enter_dyntarget(register Name target); +extern Name_vector enter_name(String string, Boolean tail_present, register wchar_t *string_start, register wchar_t *string_end, Name_vector current_names, Name_vector *extra_names, Boolean *target_group_seen); +extern Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error); +extern Doname execute_parallel(Property line, Boolean waitflg, Boolean local = false); +extern Doname execute_serial(Property line); +extern timestruc_t& exists(register Name target); +extern void fatal(char *, ...); +extern void fatal_reader(char *, ...); +extern Doname find_ar_suffix_rule(register Name target, Name true_target, Property *command, Boolean rechecking); +extern Doname find_double_suffix_rule(register Name target, Property *command, Boolean rechecking); +extern Doname find_percent_rule(register Name target, Property *command, Boolean rechecking); +extern int find_run_directory (char *cmd, char *cwd, char *dir, char **pgm, char **run, char *path); +extern Doname find_suffix_rule(Name target, Name target_body, Name target_suffix, Property *command, Boolean rechecking); +extern Chain find_target_groups(register Name_vector target_list, register int i, Boolean reset); +extern void finish_children(Boolean docheck); +extern void finish_running(void); +extern void free_chain(Name_vector ptr); +extern void gather_recursive_deps(void); +extern char *get_current_path(void); +extern int get_job_msg_id(void); +extern FILE *get_mtool_msgs_fp(void); +#ifdef DISTRIBUTED +extern Boolean get_dmake_group_specified(void); +extern Boolean get_dmake_max_jobs_specified(void); +extern Boolean get_dmake_mode_specified(void); +extern Boolean get_dmake_odir_specified(void); +extern Boolean get_dmake_rcfile_specified(void); +extern Boolean get_pmake_machinesfile_specified(void); +#endif +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +extern XDR *get_xdrs_ptr(void); +#endif +extern wchar_t *getmem_wc(register int size); +#if !defined(linux) +/* On linux getwd(char *) is defined in 'unistd.h' */ +#ifdef __cplusplus +extern "C" { +#endif +extern char *getwd(char *); +#ifdef __cplusplus +} +#endif +#endif +extern void handle_interrupt(int); +extern Boolean is_running(Name target); +extern void load_cached_names(void); +extern Boolean parallel_ok(Name target, Boolean line_prop_must_exists); +extern void print_dependencies(register Name target, register Property line); +extern void send_job_start_msg(Property line); +extern void send_rsrc_info_msg(int max_jobs, char *hostname, char *username); +extern void print_value(register Name value, Daemon daemon); +extern timestruc_t& read_archive(register Name target); +extern int read_dir(Name dir, wchar_t *pattern, Property line, wchar_t *library); +extern void read_directory_of_file(register Name file); +extern int read_make_machines(Name make_machines_name); +extern Boolean read_simple_file(register Name makefile_name, register Boolean chase_path, register Boolean doname_it, Boolean complain, Boolean must_exist, Boolean report_file, Boolean lock_makefile); +extern void remove_recursive_dep(Name target); +extern void report_recursive_dep(Name target, char *line); +extern void report_recursive_done(void); +extern void report_recursive_init(void); +extern Recursive_make find_recursive_target(Name target); +extern void reset_locals(register Name target, register Property old_locals, register Property conditional, register int index); +extern void set_locals(register Name target, register Property old_locals); +extern void setvar_append(register Name name, register Name value); +#ifdef DISTRIBUTED +extern void setvar_envvar(Avo_DoJobMsg *dmake_job_msg); +#else +extern void setvar_envvar(void); +#endif +extern void special_reader(Name target, register Name_vector depes, Cmd_line command); +extern void startup_rxm(); +extern Doname target_can_be_built(register Name target); +extern char *time_to_string(const timestruc_t &time); +extern void update_target(Property line, Doname result); +extern void warning(char *, ...); +extern void write_state_file(int report_recursive, Boolean exiting); +extern Name vpath_translation(register Name cmd); + +#define DEPINFO_FMT_VERSION "VERS2$" +#define VER_LEN strlen(DEPINFO_FMT_VERSION) + +#ifdef NSE + +/* + * NSE version for depinfo format + */ +extern Boolean nse; +extern Name nse_backquote_seen; +extern Boolean nse_did_recursion; +extern Name nse_shell_var_used; +extern Boolean nse_watch_vars; +extern wchar_t current_makefile[MAXPATHLEN]; +extern Boolean nse_depinfo_locked; +extern char nse_depinfo_lockfile[MAXPATHLEN]; +extern Name derived_src; + +extern void depvar_dep_macro_used(Name); +extern void depvar_rule_macro_used(Name); +extern Boolean nse_backquotes(wchar_t *); +extern void nse_check_cd(Property); +extern void nse_check_derived_src(Name, wchar_t *, Cmd_line); +extern void nse_check_file_backquotes(wchar_t *); +extern void nse_check_no_deps_no_rule(Name, Property, Property); +extern void nse_check_sccs(wchar_t *, wchar_t *); +extern void nse_dep_cmdmacro(wchar_t *); +extern int nse_exit_status(void); +extern void nse_init_source_suffixes(void); +extern void nse_no_makefile(Name); +extern void nse_rule_cmdmacro(wchar_t *); +extern void nse_wildcard(wchar_t *, wchar_t *); +#endif + +#endif diff --git a/usr/src/make_src/Make/include/mksdmsi18n/mksdmsi18n.h b/usr/src/make_src/Make/include/mksdmsi18n/mksdmsi18n.h new file mode 100644 index 0000000..d8b55eb --- /dev/null +++ b/usr/src/make_src/Make/include/mksdmsi18n/mksdmsi18n.h @@ -0,0 +1,44 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1996 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)mksdmsi18n.h 1.3 06/12/12 + */ + +#pragma ident "@(#)mksdmsi18n.h 1.3 06/12/12" + +#ifndef _AVO_MKSDMSI18N_H +#define _AVO_MKSDMSI18N_H + +#ifndef _AVO_INTL_H +#include <avo/intl.h> +#endif + +extern nl_catd libmksdmsi18n_catd; + +int libmksdmsi18n_init(); +void libmksdmsi18n_fini(); + +#endif + diff --git a/usr/src/make_src/Make/include/mksh/defs.h b/usr/src/make_src/Make/include/mksh/defs.h new file mode 100644 index 0000000..e8ae60e --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/defs.h @@ -0,0 +1,1042 @@ +#ifndef _MKSH_DEFS_H +#define _MKSH_DEFS_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)defs.h 1.35 06/12/12 + */ + +#pragma ident "@(#)defs.h 1.35 06/12/12" + +/* + * This is not "#ifdef TEAMWARE_MAKE_CMN" because we're currently + * using the TW fake i18n headers and libraries to build both + * SMake and PMake on SPARC/S1 and x86/S2. + */ + +#include <avo/intl.h> +#include <limits.h> /* MB_LEN_MAX */ +#include <stdio.h> +#include <stdlib.h> /* wchar_t */ +#include <string.h> /* strcmp() */ +#include <nl_types.h> /* catgets() */ +#include <sys/param.h> /* MAXPATHLEN */ +#include <sys/types.h> /* time_t, caddr_t */ +#include <vroot/vroot.h> /* pathpt */ +#include <sys/time.h> /* timestruc_t */ +#include <errno.h> /* errno */ + +#if defined (HP_UX) || defined (linux) +#define MAXNAMELEN 256 +#define RW_NO_OVERLOAD_WCHAR 1 /* Rogue Wave, belongs in <rw/compiler.h> */ +#else +#include <wctype.h> +#include <widec.h> +#endif + +#if defined (linux) +/* + * Definition of wchar functions. + */ +# include <wctype.h> +# include <wchar.h> +# define wsdup(x) wcsdup(x) +# define wschr(x,y) wcschr(x,y) +# define wscat(x,y) wcscat(x,y) +# define wsrchr(x,y) wcsrchr(x,y) +# define wslen(x) wcslen(x) +# define wscpy(x,y) wcscpy(x,y) +# define wsncpy(x,y,z) wcsncpy(x,y,z) +# define wscmp(x,y) wcscmp(x,y) +# define wsncmp(x,y,z) wcsncmp(x,y,z) +#endif + +/* + * A type and some utilities for boolean values + */ + +#define false BOOLEAN_false +#define true BOOLEAN_true + +typedef enum { + false = 0, + true = 1, + failed = 0, + succeeded = 1 +} Boolean; +#define BOOLEAN(expr) ((expr) ? true : false) + +/* + * Some random constants (in an enum so dbx knows their values) + */ +enum { + update_delay = 30, /* time between rstat checks */ +#ifdef sun386 + ar_member_name_len = 14, +#else +#if defined(SUN5_0) || defined(linux) + ar_member_name_len = 1024, +#else + ar_member_name_len = 15, +#endif +#endif + + hashsize = 2048 /* size of hash table */ +}; + + +/* + * Symbols that defines all the different char constants make uses + */ +enum { + ampersand_char = '&', + asterisk_char = '*', + at_char = '@', + backquote_char = '`', + backslash_char = '\\', + bar_char = '|', + braceleft_char = '{', + braceright_char = '}', + bracketleft_char = '[', + bracketright_char = ']', + colon_char = ':', + comma_char = ',', + dollar_char = '$', + doublequote_char = '"', + equal_char = '=', + exclam_char = '!', + greater_char = '>', + hat_char = '^', + hyphen_char = '-', + less_char = '<', + newline_char = '\n', + nul_char = '\0', + numbersign_char = '#', + parenleft_char = '(', + parenright_char = ')', + percent_char = '%', + period_char = '.', + plus_char = '+', + question_char = '?', + quote_char = '\'', + semicolon_char = ';', + slash_char = '/', + space_char = ' ', + tab_char = '\t', + tilde_char = '~' +}; + +/* + * For make i18n. Codeset independent. + * Setup character semantics by identifying all the special characters + * of make, and assigning each an entry in the char_semantics[] vector. + */ +enum { + ampersand_char_entry = 0, /* 0 */ + asterisk_char_entry, /* 1 */ + at_char_entry, /* 2 */ + backquote_char_entry, /* 3 */ + backslash_char_entry, /* 4 */ + bar_char_entry, /* 5 */ + bracketleft_char_entry, /* 6 */ + bracketright_char_entry, /* 7 */ + colon_char_entry, /* 8 */ + dollar_char_entry, /* 9 */ + doublequote_char_entry, /* 10 */ + equal_char_entry, /* 11 */ + exclam_char_entry, /* 12 */ + greater_char_entry, /* 13 */ + hat_char_entry, /* 14 */ + hyphen_char_entry, /* 15 */ + less_char_entry, /* 16 */ + newline_char_entry, /* 17 */ + numbersign_char_entry, /* 18 */ + parenleft_char_entry, /* 19 */ + parenright_char_entry, /* 20 */ + percent_char_entry, /* 21 */ + plus_char_entry, /* 22 */ + question_char_entry, /* 23 */ + quote_char_entry, /* 24 */ + semicolon_char_entry, /* 25 */ +#ifdef SGE_SUPPORT + space_char_entry, /* 26 */ + tab_char_entry, /* 27 */ + no_semantics_entry /* 28 */ +#else + no_semantics_entry /* 26 */ +#endif /* SGE_SUPPORT */ +}; + +/* + * CHAR_SEMANTICS_ENTRIES should be the number of entries above. + * The last entry in char_semantics[] should be blank. + */ +#ifdef SGE_SUPPORT +#define CHAR_SEMANTICS_ENTRIES 29 +/* +#define CHAR_SEMANTICS_STRING "&*@`\\|[]:$=!>-\n#()%+?;^<'\" \t" + */ +#else +#define CHAR_SEMANTICS_ENTRIES 27 +/* +#define CHAR_SEMANTICS_STRING "&*@`\\|[]:$=!>-\n#()%+?;^<'\"" + */ +#endif /* SGE_SUPPORT */ + +/* + * Some utility macros + */ +#define ALLOC(x) ((struct _##x *)getmem(sizeof (struct _##x))) +#define ALLOC_WC(x) ((wchar_t *)getmem((x) * SIZEOFWCHAR_T)) +#define FIND_LENGTH -1 +#define GETNAME(a,b) getname_fn((a), (b), false) +#define IS_EQUAL(a,b) (!strcmp((a), (b))) +#define IS_EQUALN(a,b,n) (!strncmp((a), (b), (n))) +#define IS_WEQUAL(a,b) (!wscmp((a), (b))) +#define IS_WEQUALN(a,b,n) (!wsncmp((a), (b), (n))) +#define MBLEN(a) mblen((a), MB_LEN_MAX) +#define MBSTOWCS(a,b) (void) mbstowcs_with_check((a), (b), MAXPATHLEN) +#define MBTOWC(a,b) mbtowc((a), (b), MB_LEN_MAX) +#define SIZEOFWCHAR_T (sizeof (wchar_t)) +#define VSIZEOF(v) (sizeof (v) / sizeof ((v)[0])) +#define WCSTOMBS(a,b) (void) wcstombs((a), (b), (MAXPATHLEN * MB_LEN_MAX)) +#define WCTOMB(a,b) (void) wctomb((a), (b)) +#define HASH(v, c) (v = (v)*31 + (unsigned int)(c)) + +extern void mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n); + +/* + * Bits stored in funny vector to classify chars + */ +enum { + dollar_sem = 0001, + meta_sem = 0002, + percent_sem = 0004, + wildcard_sem = 0010, + command_prefix_sem = 0020, + special_macro_sem = 0040, + colon_sem = 0100, + parenleft_sem = 0200 +}; + +/* + * Type returned from doname class functions + */ +typedef enum { + build_dont_know = 0, + build_failed, + build_ok, + build_in_progress, + build_running, /* PARALLEL & DISTRIBUTED */ + build_pending, /* PARALLEL & DISTRIBUTED */ + build_serial, /* PARALLEL & DISTRIBUTED */ + build_subtree /* PARALLEL & DISTRIBUTED */ +} Doname; + +/* + * The String struct defines a string with the following layout + * "xxxxxxxxxxxxxxxCxxxxxxxxxxxxxxx________" + * ^ ^ ^ ^ + * | | | | + * buffer.start text.p text.end buffer.end + * text.p points to the next char to read/write. + */ +struct _String { + struct Text { + wchar_t *p; /* Read/Write pointer */ + wchar_t *end; /* Read limit pointer */ + } text; + struct Physical_buffer { + wchar_t *start; /* Points to start of buffer */ + wchar_t *end; /* End of physical buffer */ + } buffer; + Boolean free_after_use:1; +}; + +#define STRING_BUFFER_LENGTH 1024 +#define INIT_STRING_FROM_STACK(str, buf) { \ + str.buffer.start = (buf); \ + str.text.p = (buf); \ + str.text.end = NULL; \ + str.buffer.end = (buf) \ + + (sizeof (buf)/SIZEOFWCHAR_T); \ + str.free_after_use = false; \ + } + +#define APPEND_NAME(np, dest, len) append_string((np)->string_mb, (dest), (len)); + +class Wstring { + public: + struct _String string; + wchar_t string_buf[STRING_BUFFER_LENGTH]; + + public: + Wstring(); + Wstring(struct _Name * name); + ~Wstring(); + + void init(struct _Name * name); + void init(wchar_t * name, unsigned length); + unsigned length() { + return wslen(string.buffer.start); + }; + void append_to_str(struct _String * str, unsigned off, unsigned length); + + wchar_t * get_string() { + return string.buffer.start; + }; + + wchar_t * get_string(unsigned off) { + return string.buffer.start + off; + }; + + Boolean equaln(wchar_t * str, unsigned length); + Boolean equal(wchar_t * str); + Boolean equal(wchar_t * str, unsigned off); + Boolean equal(wchar_t * str, unsigned off, unsigned length); + + Boolean equaln(Wstring * str, unsigned length); + Boolean equal(Wstring * str); + Boolean equal(Wstring * str, unsigned off); + Boolean equal(Wstring * str, unsigned off, unsigned length); +}; + + +/* + * Used for storing the $? list and also for the "target + target:" + * construct. + */ +struct _Chain { + struct _Chain *next; + struct _Name *name; + struct _Percent *percent_member; +}; + +/* + * Stores one command line for a rule + */ +struct _Cmd_line { + struct _Cmd_line *next; + struct _Name *command_line; + Boolean make_refd:1; /* $(MAKE) referenced? */ + /* + * Remember any command line prefixes given + */ + Boolean ignore_command_dependency:1; /* `?' */ + Boolean assign:1; /* `=' */ + Boolean ignore_error:1; /* `-' */ + Boolean silent:1; /* `@' */ + Boolean always_exec:1; /* `+' */ +}; + +/* + * Linked list of targets/files + */ +struct _Dependency { + struct _Dependency *next; + struct _Name *name; + Boolean automatic:1; + Boolean stale:1; + Boolean built:1; +}; + +/* + * The specials are markers for targets that the reader should special case + */ +typedef enum { + no_special, + built_last_make_run_special, + default_special, +#ifdef NSE + derived_src_special, +#endif + get_posix_special, + get_special, + ignore_special, + keep_state_file_special, + keep_state_special, + make_version_special, + no_parallel_special, + parallel_special, + posix_special, + precious_special, + sccs_get_posix_special, + sccs_get_special, + silent_special, + suffixes_special, + svr4_special, + localhost_special +} Special; + +typedef enum { + no_colon, + one_colon, + two_colon, + equal_seen, + conditional_seen, + none_seen +} Separator; + +/* + * Magic values for the timestamp stored with each name object + */ + +#if defined (linux) +typedef struct timespec timestruc_t; +#endif + +extern const timestruc_t file_no_time; +extern const timestruc_t file_doesnt_exist; +extern const timestruc_t file_is_dir; +extern const timestruc_t file_min_time; +extern const timestruc_t file_max_time; + +/* + * Each Name has a list of properties + * The properties are used to store information that only + * a subset of the Names need + */ +typedef enum { + no_prop, + conditional_prop, + line_prop, + macro_prop, + makefile_prop, + member_prop, + recursive_prop, + sccs_prop, + suffix_prop, + target_prop, + time_prop, + vpath_alias_prop, + long_member_name_prop, + macro_append_prop, + env_mem_prop +} Property_id; + +typedef enum { + no_daemon = 0, + chain_daemon +} Daemon; + +struct _Env_mem { + char *value; +}; + +struct _Macro_appendix { + struct _Name *value; + struct _Name *value_to_append; +}; + +struct _Macro { + /* + * For "ABC = xyz" constructs + * Name "ABC" get one macro prop + */ + struct _Name *value; +#ifdef NSE + Boolean imported:1; +#endif + Boolean exported:1; + Boolean read_only:1; + /* + * This macro is defined conditionally + */ + Boolean is_conditional:1; + /* + * The list for $? is stored as a structured list that + * is translated into a string iff it is referenced. + * This is why some macro values need a daemon. + */ +#if defined(HP_UX) || defined(linux) + Daemon daemon; +#else + Daemon daemon:2; +#endif +}; + +struct _Macro_list { + struct _Macro_list *next; + char *macro_name; + char *value; +}; + +enum sccs_stat { + DONT_KNOW_SCCS = 0, + NO_SCCS, + HAS_SCCS +}; + +struct _Name { + struct _Property *prop; /* List of properties */ + char *string_mb; /* Multi-byte name string */ + struct { + unsigned int length; + } hash; + struct { + timestruc_t time; /* Modification */ + int stat_errno; /* error from "stat" */ + off_t size; /* Of file */ + mode_t mode; /* Of file */ +#if defined(HP_UX) || defined(linux) + Boolean is_file; + Boolean is_dir; + Boolean is_sym_link; + Boolean is_precious; + enum sccs_stat has_sccs; +#else + Boolean is_file:1; + Boolean is_dir:1; + Boolean is_sym_link:1; + Boolean is_precious:1; +#ifdef NSE + Boolean is_derived_src:1; +#endif + enum sccs_stat has_sccs:2; +#endif + } stat; + /* + * Count instances of :: definitions for this target + */ + short colon_splits; + /* + * We only clear the automatic depes once per target per report + */ + short temp_file_number; + /* + * Count how many conditional macros this target has defined + */ + short conditional_cnt; + /* + * A conditional macro was used when building this target + */ + Boolean depends_on_conditional:1; + /* + * Pointer to list of conditional macros which were used to build + * this target + */ + struct _Macro_list *conditional_macro_list; + Boolean has_member_depe:1; + Boolean is_member:1; + /* + * This target is a directory that has been read + */ + Boolean has_read_dir:1; + /* + * This name is a macro that is now being expanded + */ + Boolean being_expanded:1; + /* + * This name is a magic name that the reader must know about + */ +#if defined(HP_UX) || defined(linux) + Special special_reader; + Doname state; + Separator colons; +#else + Special special_reader:5; + Doname state:3; + Separator colons:3; +#endif + Boolean has_depe_list_expanded:1; + Boolean suffix_scan_done:1; + Boolean has_complained:1; /* For sccs */ + /* + * This target has been built during this make run + */ + Boolean ran_command:1; + Boolean with_squiggle:1; /* for .SUFFIXES */ + Boolean without_squiggle:1; /* for .SUFFIXES */ + Boolean has_read_suffixes:1; /* Suffix list cached*/ + Boolean has_suffixes:1; + Boolean has_target_prop:1; + Boolean has_vpath_alias_prop:1; + Boolean dependency_printed:1; /* For dump_make_state() */ + Boolean dollar:1; /* In namestring */ + Boolean meta:1; /* In namestring */ + Boolean percent:1; /* In namestring */ + Boolean wildcard:1; /* In namestring */ + Boolean has_parent:1; + Boolean is_target:1; + Boolean has_built:1; + Boolean colon:1; /* In namestring */ + Boolean parenleft:1; /* In namestring */ + Boolean has_recursive_dependency:1; + Boolean has_regular_dependency:1; + Boolean is_double_colon:1; + Boolean is_double_colon_parent:1; + Boolean has_long_member_name:1; + /* + * allowed to run in parallel + */ + Boolean parallel:1; + /* + * not allowed to run in parallel + */ + Boolean no_parallel:1; + /* + * used in dependency_conflict + */ + Boolean checking_subtree:1; + Boolean added_pattern_conditionals:1; + /* + * rechecking target for possible rebuild + */ + Boolean rechecking_target:1; + /* + * build this target in silent mode + */ + Boolean silent_mode:1; + /* + * build this target in ignore error mode + */ + Boolean ignore_error_mode:1; + Boolean dont_activate_cond_values:1; + /* + * allowed to run serially on local host + */ + Boolean localhost:1; +}; + +/* + * Stores the % matched default rules + */ +struct _Percent { + struct _Percent *next; + struct _Name **patterns; + struct _Name *name; + struct _Percent *dependencies; + struct _Cmd_line *command_template; + struct _Chain *target_group; + int patterns_total; + Boolean being_expanded; +}; + +struct Conditional { + /* + * For "foo := ABC [+]= xyz" constructs + * Name "foo" gets one conditional prop + */ + struct _Name *target; + struct _Name *name; + struct _Name *value; + int sequence; + Boolean append:1; +}; + +struct Line { + /* + * For "target : dependencies" constructs + * Name "target" gets one line prop + */ + struct _Cmd_line *command_template; + struct _Cmd_line *command_used; + struct _Dependency *dependencies; + timestruc_t dependency_time; + struct _Chain *target_group; + Boolean is_out_of_date:1; + Boolean sccs_command:1; + Boolean command_template_redefined:1; + Boolean dont_rebuild_command_used:1; + /* + * Values for the dynamic macros + */ + struct _Name *target; + struct _Name *star; + struct _Name *less; + struct _Name *percent; + struct _Chain *query; +}; + +struct Makefile { + /* + * Names that reference makefiles gets one prop + */ + wchar_t *contents; + off_t size; +}; + +struct Member { + /* + * For "lib(member)" and "lib((entry))" constructs + * Name "lib(member)" gets one member prop + * Name "lib((entry))" gets one member prop + * The member field is filled in when the prop is refd + */ + struct _Name *library; + struct _Name *entry; + struct _Name *member; +}; + +struct Recursive { + /* + * For "target: .RECURSIVE dir makefiles" constructs + * Used to keep track of recursive calls to make + * Name "target" gets one recursive prop + */ + struct _Name *directory; + struct _Name *target; + struct _Dependency *makefiles; + Boolean has_built; + Boolean in_depinfo; +}; + +struct Sccs { + /* + * Each file that has a SCCS s. file gets one prop + */ + struct _Name *file; +}; + +struct Suffix { + /* + * Cached list of suffixes that can build this target + * suffix is built from .SUFFIXES + */ + struct _Name *suffix; + struct _Cmd_line *command_template; +}; + +struct Target { + /* + * For "target:: dependencies" constructs + * The "::" construct is handled by converting it to + * "foo: 1@foo" + "1@foo: dependecies" + * "1@foo" gets one target prop + * This target prop cause $@ to be bound to "foo" + * not "1@foo" when the rule is evaluated + */ + struct _Name *target; +}; + +struct STime { + /* + * Save the original time for :: targets + */ + timestruc_t time; +}; + +struct Vpath_alias { + /* + * If a file was found using the VPATH it gets + * a vpath_alias prop + */ + struct _Name *alias; +}; + +struct Long_member_name { + /* + * Targets with a truncated member name carries + * the full lib(member) name for the state file + */ + struct _Name *member_name; +}; + +union Body { + struct _Macro macro; + struct Conditional conditional; + struct Line line; + struct Makefile makefile; + struct Member member; + struct Recursive recursive; + struct Sccs sccs; + struct Suffix suffix; + struct Target target; + struct STime time; + struct Vpath_alias vpath_alias; + struct Long_member_name long_member_name; + struct _Macro_appendix macro_appendix; + struct _Env_mem env_mem; +}; + +#define PROPERTY_HEAD_SIZE (sizeof (struct _Property)-sizeof (union Body)) +struct _Property { + struct _Property *next; +#if defined(HP_UX) || defined(linux) + Property_id type; +#else + Property_id type:4; +#endif + union Body body; +}; + +/* Structure for dynamic "ascii" arrays */ +struct ASCII_Dyn_Array { + char *start; + size_t size; +}; + +struct _Envvar { + struct _Name *name; + struct _Name *value; + struct _Envvar *next; + char *env_string; + Boolean already_put:1; +}; + +/* + * Macros for the reader + */ +#define GOTO_STATE(new_state) { \ + SET_STATE(new_state); \ + goto enter_state; \ + } +#define SET_STATE(new_state) state = (new_state) + +#define UNCACHE_SOURCE() if (source != NULL) { \ + source->string.text.p = source_p; \ + } +#define CACHE_SOURCE(comp) if (source != NULL) { \ + source_p = source->string.text.p - \ + (comp); \ + source_end = source->string.text.end; \ + } +#define GET_NEXT_BLOCK_NOCHK(source) { UNCACHE_SOURCE(); \ + source = get_next_block_fn(source); \ + CACHE_SOURCE(0) \ + } +#define GET_NEXT_BLOCK(source) { GET_NEXT_BLOCK_NOCHK(source); \ + if (source != NULL && source->error_converting) { \ + GOTO_STATE(illegal_bytes_state); \ + } \ + } +#define GET_CHAR() ((source == NULL) || \ + (source_p >= source_end) ? 0 : *source_p) + +struct _Source { + struct _String string; + struct _Source *previous; + off_t bytes_left_in_file; + short fd; + Boolean already_expanded:1; + Boolean error_converting:1; + char *inp_buf; + char *inp_buf_end; + char *inp_buf_ptr; +}; + +typedef enum { + reading_nothing, + reading_makefile, + reading_statefile, + rereading_statefile, + reading_cpp_file +} Makefile_type; + +/* + * Typedefs for all structs + */ +typedef struct _Chain *Chain, Chain_rec; +typedef struct _Envvar *Envvar, Envvar_rec; +typedef struct _Macro_list *Macro_list, Macro_list_rec; +typedef struct _Name *Name, Name_rec; +typedef struct _Property *Property, Property_rec; +typedef struct _Source *Source, Source_rec; +typedef struct _String *String, String_rec; + +/* + * name records hash table. + */ +struct Name_set { +private: + // single node in a tree + struct entry { + entry(Name name_, entry *parent_) : + name(name_), + parent(parent_), + left(0), + right(0), + depth(1) + {} + + Name name; + + entry *parent; + entry *left; + entry *right; + unsigned depth; + + void setup_depth() { + unsigned rdepth = (right != 0) ? right->depth : 0; + unsigned ldepth = (left != 0) ? left->depth : 0; + depth = 1 + ((ldepth > rdepth) ? ldepth : rdepth); + } + }; + +public: + // make iterator a friend of Name_set to have access to struct entry + struct iterator; + friend struct Name_set::iterator; + + // iterator over tree nodes + struct iterator { + public: + // constructors + iterator() : node(0) {} + iterator(entry *node_) : node(node_) {} + + // dereference operator + Name operator->() const { return node->name; } + + // conversion operator + operator Name() { return node->name; } + + // assignment operator + iterator& operator=(const iterator &o) { node = o.node; return *this; } + + // equality/inequality operators + int operator==(const iterator &o) const { return (node == o.node); } + int operator!=(const iterator &o) const { return (node != o.node); } + + // pre/post increment operators + iterator& operator++(); + iterator operator++(int) { iterator it = *this; ++*this; return it; } + + private: + // the node iterator points to + entry *node; + }; + +public: + // constructor + Name_set() : root(0) {} + + // lookup, insert and remove operations + Name lookup(const char *key); + Name insert(const char *key, Boolean &found); + void insert(Name name); + + // begin/end iterators + iterator begin() const; + iterator end() const { return iterator(); } + +private: + // rebalance given node + void rebalance(entry *node); + +private: + // tree root + entry *root; +}; + +/* + * extern declarations for all global variables. + * The actual declarations are in globals.cc + */ +extern char char_semantics[]; +extern wchar_t char_semantics_char[]; +extern Macro_list cond_macro_list; +extern Boolean conditional_macro_used; +extern Boolean do_not_exec_rule; /* `-n' */ +extern Boolean dollarget_seen; +extern Boolean dollarless_flag; +extern Name dollarless_value; +extern char **environ; +extern Envvar envvar; +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) +extern int exit_status; +#endif +extern wchar_t *file_being_read; +/* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */ +extern Boolean gnu_style; +extern Name_set hashtab; +extern Name host_arch; +extern Name host_mach; +extern int line_number; +extern char *make_state_lockfile; +extern Boolean make_word_mentioned; +extern Makefile_type makefile_type; +extern char mbs_buffer[]; +extern Name path_name; +extern Boolean posix; +extern Name query; +extern Boolean query_mentioned; +extern Name hat; +extern Boolean reading_environment; +extern Name shell_name; +extern Boolean svr4; +extern Name target_arch; +extern Name target_mach; +extern Boolean tilde_rule; +extern wchar_t wcs_buffer[]; +extern Boolean working_on_targets; +extern Name virtual_root; +extern Boolean vpath_defined; +extern Name vpath_name; +extern Boolean make_state_locked; +#if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR) +extern Boolean out_err_same; +#endif +extern pid_t childPid; +extern nl_catd libmksh_catd; + +/* + * RFE 1257407: make does not use fine granularity time info available from stat. + * High resolution time comparison. + */ + +inline int +operator==(const timestruc_t &t1, const timestruc_t &t2) { + return ((t1.tv_sec == t2.tv_sec) && (t1.tv_nsec == t2.tv_nsec)); +} + +inline int +operator!=(const timestruc_t &t1, const timestruc_t &t2) { + return ((t1.tv_sec != t2.tv_sec) || (t1.tv_nsec != t2.tv_nsec)); +} + +inline int +operator>(const timestruc_t &t1, const timestruc_t &t2) { + if (t1.tv_sec == t2.tv_sec) { + return (t1.tv_nsec > t2.tv_nsec); + } + return (t1.tv_sec > t2.tv_sec); +} + +inline int +operator>=(const timestruc_t &t1, const timestruc_t &t2) { + if (t1.tv_sec == t2.tv_sec) { + return (t1.tv_nsec >= t2.tv_nsec); + } + return (t1.tv_sec > t2.tv_sec); +} + +inline int +operator<(const timestruc_t &t1, const timestruc_t &t2) { + if (t1.tv_sec == t2.tv_sec) { + return (t1.tv_nsec < t2.tv_nsec); + } + return (t1.tv_sec < t2.tv_sec); +} + +inline int +operator<=(const timestruc_t &t1, const timestruc_t &t2) { + if (t1.tv_sec == t2.tv_sec) { + return (t1.tv_nsec <= t2.tv_nsec); + } + return (t1.tv_sec < t2.tv_sec); +} + +#endif diff --git a/usr/src/make_src/Make/include/mksh/dosys.h b/usr/src/make_src/Make/include/mksh/dosys.h new file mode 100644 index 0000000..daab07b --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/dosys.h @@ -0,0 +1,50 @@ +#ifndef _MKSH_DOSYS_H +#define _MKSH_DOSYS_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)dosys.h 1.9 06/12/12 + */ + +#pragma ident "@(#)dosys.h 1.9 06/12/12" + +#include <mksh/defs.h> +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +# include <rw/xdrstrea.h> +#endif +#include <vroot/vroot.h> + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +extern Boolean await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, Boolean send_mtool_msgs, XDR *xdrs, int job_msg_id); +#else +extern Boolean await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, Boolean send_mtool_msgs, void *xdrs, int job_msg_id); +#endif +extern int doexec(register wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio); +extern int doshell(wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, int nice_prio); +extern Doname dosys_mksh(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio); +extern void redirect_io(char *stdout_file, char *stderr_file); +extern void sh_command2string(register String command, register String destination); + +#endif diff --git a/usr/src/make_src/Make/include/mksh/globals.h b/usr/src/make_src/Make/include/mksh/globals.h new file mode 100644 index 0000000..129dbee --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/globals.h @@ -0,0 +1,35 @@ +#ifndef _MKSH_GLOBALS_H +#define _MKSH_GLOBALS_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)globals.h 1.2 06/12/12 + */ + +#pragma ident "@(#)globals.h 1.2 06/12/12" + +#include <mksh/defs.h> + +#endif diff --git a/usr/src/make_src/Make/include/mksh/i18n.h b/usr/src/make_src/Make/include/mksh/i18n.h new file mode 100644 index 0000000..7c9e3c4 --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/i18n.h @@ -0,0 +1,38 @@ +#ifndef _MKSH_I18N_H +#define _MKSH_I18N_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)i18n.h 1.2 06/12/12 + */ + +#pragma ident "@(#)i18n.h 1.2 06/12/12" + +#include <mksh/defs.h> + +extern int get_char_semantics_entry(wchar_t ch); +extern char get_char_semantics_value(wchar_t ch); + +#endif diff --git a/usr/src/make_src/Make/include/mksh/libmksh_init.h b/usr/src/make_src/Make/include/mksh/libmksh_init.h new file mode 100644 index 0000000..7190b06 --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/libmksh_init.h @@ -0,0 +1,36 @@ +#ifndef _MKSH_INIT_H +#define _MKSH_INIT_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1995 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)libmksh_init.h 1.2 06/12/12 + */ + +#pragma ident "@(#)libmksh_init.h 1.2 06/12/12" + +int libmksh_init() +void libmksh_fini(); + +#endif diff --git a/usr/src/make_src/Make/include/mksh/macro.h b/usr/src/make_src/Make/include/mksh/macro.h new file mode 100644 index 0000000..5989c9e --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/macro.h @@ -0,0 +1,41 @@ +#ifndef _MKSH_MACRO_H +#define _MKSH_MACRO_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2002 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)macro.h 1.3 06/12/12 + */ + +#pragma ident "@(#)macro.h 1.3 06/12/12" + +#include <mksh/defs.h> + +extern void expand_macro(register Source source, register String destination, wchar_t *current_string, Boolean cmd); +extern void expand_value(Name value, register String destination, Boolean cmd); +extern Name getvar(register Name name); + +extern Property setvar_daemon(register Name name, register Name value, Boolean append, Daemon daemon, Boolean strip_trailing_spaces, short debug_level); + +#endif diff --git a/usr/src/make_src/Make/include/mksh/misc.h b/usr/src/make_src/Make/include/mksh/misc.h new file mode 100644 index 0000000..bb397fc --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/misc.h @@ -0,0 +1,60 @@ +#ifndef _MKSH_MISC_H +#define _MKSH_MISC_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)misc.h 1.4 06/12/12 + */ + +#pragma ident "@(#)misc.h 1.4 06/12/12" + +#include <mksh/defs.h> + +extern void append_char(wchar_t from, register String to); +extern Property append_prop(register Name target, register Property_id type); +extern void append_string(register wchar_t *from, register String to, register int length); +extern void enable_interrupt(register void (*handler) (int)); +extern char *errmsg(int errnum); +extern void fatal_mksh(char * message, ...); +extern void fatal_reader_mksh(char * pattern, ...); +extern char *get_current_path_mksh(void); +extern Property get_prop(register Property start, register Property_id type); +extern char *getmem(register int size); +extern Name getname_fn(wchar_t *name, register int len, register Boolean dont_enter, register Boolean * foundp = NULL); +extern void store_name(Name name); +extern void free_name(Name name); +extern void handle_interrupt_mksh(int); +extern Property maybe_append_prop(register Name target, register Property_id type); +extern void retmem(wchar_t *p); +extern void retmem_mb(caddr_t p); +extern void setup_char_semantics(void); +extern void setup_interrupt(register void (*handler) (int)); +extern void warning_mksh(char * message, ...); + +extern void append_string(register char *from, register String to, register int length); +extern wchar_t *get_wstring(char * from); + + +#endif diff --git a/usr/src/make_src/Make/include/mksh/mksh.h b/usr/src/make_src/Make/include/mksh/mksh.h new file mode 100644 index 0000000..2b555e0 --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/mksh.h @@ -0,0 +1,49 @@ +#ifndef _MKSH_MKSH_H +#define _MKSH_MKSH_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)mksh.h 1.7 06/12/12 + */ + +#pragma ident "@(#)mksh.h 1.7 06/12/12" + +/* + * Included files + */ +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +# include <dm/Avo_DmakeCommand.h> +#endif + +#include <mksh/defs.h> +#include <unistd.h> + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + +extern int do_job(Avo_DmakeCommand *cmd_list[], char *env_list[], char *stdout_file, char *stderr_file, char *cwd, char *cnwd, int ignore, int silent, pathpt vroot_path, char *shell, int nice_prio); + +#endif /* TEAMWARE_MAKE_CMN */ + +#endif diff --git a/usr/src/make_src/Make/include/mksh/read.h b/usr/src/make_src/Make/include/mksh/read.h new file mode 100644 index 0000000..5afffd2 --- /dev/null +++ b/usr/src/make_src/Make/include/mksh/read.h @@ -0,0 +1,37 @@ +#ifndef _MKSH_READ_H +#define _MKSH_READ_H +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)read.h 1.2 06/12/12 + */ + +#pragma ident "@(#)read.h 1.2 06/12/12" + +#include <mksh/defs.h> + +extern Source get_next_block_fn(register Source source); + +#endif diff --git a/usr/src/make_src/Make/include/vroot/args.h b/usr/src/make_src/Make/include/vroot/args.h new file mode 100644 index 0000000..96795ad --- /dev/null +++ b/usr/src/make_src/Make/include/vroot/args.h @@ -0,0 +1,70 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1999 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)args.h 1.7 06/12/12 + */ + +#pragma ident "@(#)args.h 1.7 06/12/12" + +#ifndef _ARGS_H_ +#define _ARGS_H_ + +#include <sys/syscall.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/param.h> +#include <stdio.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> + +typedef enum { rw_read, rw_write} rwt, *rwpt; + +extern void translate_with_thunk(register char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw); + +union Args { + struct { int mode;} access; + struct { int mode;} chmod; + struct { int user; int group;} chown; + struct { int mode;} creat; + struct { char **argv; char **environ;} execve; + struct { struct stat *buffer;} lstat; + struct { int mode;} mkdir; + struct { char *name; int mode;} mount; + struct { int flags; int mode;} open; + struct { char *buffer; int buffer_size;} readlink; + struct { struct stat *buffer;} stat; +#ifndef SUN5_0 + struct { struct statfs *buffer;} statfs; +#endif + struct { int length;} truncate; + struct { struct timeval *time;} utimes; +}; + +extern union Args vroot_args; +extern int vroot_result; + +#endif diff --git a/usr/src/make_src/Make/include/vroot/report.h b/usr/src/make_src/Make/include/vroot/report.h new file mode 100644 index 0000000..15babab --- /dev/null +++ b/usr/src/make_src/Make/include/vroot/report.h @@ -0,0 +1,59 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)report.h 1.6 06/12/12 + */ + +#pragma ident "@(#)report.h 1.6 06/12/12" + +#ifndef _REPORT_H_ +#define _REPORT_H_ + +#include <stdio.h> + +extern FILE *get_report_file(void); +extern char *get_target_being_reported_for(void); +extern void report_dependency(register char *name); +extern int file_lock(char *name, char *lockname, int *file_locked, int timeout); +#ifdef NSE +extern char *setenv(char *name, char *value); +#endif + +#define SUNPRO_DEPENDENCIES "SUNPRO_DEPENDENCIES" +#define LD "LD" +#define COMP "COMP" + +/* the following definitions define the interface between make and + * NSE - the two systems must track each other. + */ +#define NSE_DEPINFO ".nse_depinfo" +#define NSE_DEPINFO_LOCK ".nse_depinfo.lock" +#define NSE_DEP_ENV "NSE_DEP" +#define NSE_TFS_PUSH "/usr/nse/bin/tfs_push" +#define NSE_TFS_PUSH_LEN 8 +#define NSE_VARIANT_ENV "NSE_VARIANT" +#define NSE_RT_SOURCE_NAME "Shared_Source" + +#endif diff --git a/usr/src/make_src/Make/include/vroot/vroot.h b/usr/src/make_src/Make/include/vroot/vroot.h new file mode 100644 index 0000000..faeb011 --- /dev/null +++ b/usr/src/make_src/Make/include/vroot/vroot.h @@ -0,0 +1,67 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)vroot.h 1.10 06/12/12 + */ + +#pragma ident "@(#)vroot.h 1.10 06/12/12" + +#ifndef _VROOT_H_ +#define _VROOT_H_ + +#include <stdio.h> +#include <nl_types.h> + +#define VROOT_DEFAULT ((pathpt)-1) + +typedef struct { + char *path; + short length; +} pathcellt, *pathcellpt, patht; +typedef patht *pathpt; + +extern void add_dir_to_path(register char *path, register pathpt *pointer, register int position); +extern void flush_path_cache(void); +extern void flush_vroot_cache(void); +extern char *get_path_name(void); +extern char *get_vroot_path(register char **vroot, register char **path, register char **filename); +extern char *get_vroot_name(void); +extern int open_vroot(char *path, int flags, int mode, pathpt vroot_path, pathpt vroot_vroot); +extern pathpt parse_path_string(register char *string, register int remove_slash); +extern void scan_path_first(void); +extern void scan_vroot_first(void); +extern void set_path_style(int style); + +extern int access_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot); + +extern int execve_vroot(char *path, char **argv, char **environ, pathpt vroot_path, pathpt vroot_vroot); + +extern int lstat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot); +extern int stat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot); +extern int readlink_vroot(char *path, char *buffer, int buffer_size, pathpt vroot_path, pathpt vroot_vroot); + + +extern nl_catd libvroot_catd; +#endif diff --git a/usr/src/make_src/Make/lib/Lib.mk b/usr/src/make_src/Make/lib/Lib.mk new file mode 100644 index 0000000..2bf2147 --- /dev/null +++ b/usr/src/make_src/Make/lib/Lib.mk @@ -0,0 +1,67 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2001 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Lib.mk 1.13 06/12/12 +# + +# Definitions of the libraries supplied by make/dmake. +# You must correctly define TOP before including this file! + +MAKE_TOP = $(TOP)/Make + +LIBBSD_DIR = $(MAKE_TOP)/lib/bsd +LIBBSD = $(LIBBSD_DIR)/$(VARIANT)/libbsd.a + +LIBDMRXM_DIR = $(MAKE_TOP)/lib/dmrxm +LIBDMRXM = $(LIBDMRXM_DIR)/$(VARIANT)/libdmrxm.a + +LIBDMRXS_DIR = $(MAKE_TOP)/lib/dmrxs +LIBDMRXS = $(LIBDMRXS_DIR)/$(VARIANT)/libdmrxs.a + +LIBMAKESTATE_DIR = $(MAKE_TOP)/lib/makestate +LIBMAKESTATE = $(LIBMAKESTATE_DIR)/$(VARIANT)/libmakestate.a + +LIBMKSDMSI18N_DIR = $(MAKE_TOP)/lib/mksdmsi18n +LIBMKSDMSI18N = $(LIBMKSDMSI18N_DIR)/$(VARIANT)/libmksdmsi18n.a + +LIBMKSH_DIR = $(MAKE_TOP)/lib/mksh +LIBMKSH = $(LIBMKSH_DIR)/$(VARIANT)/libmksh.a + +LIBVROOT_DIR = $(MAKE_TOP)/lib/vroot +LIBVROOT = $(LIBVROOT_DIR)/$(VARIANT)/libvroot.a + +LIBDM_DIR = $(MAKE_TOP)/lib/dm +LIBDM = $(LIBDM_DIR)/$(VARIANT)/libdm.a + +LIBDMCONF_DIR = $(MAKE_TOP)/lib/dmconf +LIBDMCONF = $(LIBDMCONF_DIR)/$(VARIANT)/libdmconf.a + +LIBDMRC_DIR = $(MAKE_TOP)/lib/dmrc +LIBDMRC = $(LIBDMRC_DIR)/$(VARIANT)/libdmrc.a + +LIBDMTHREAD_DIR = $(MAKE_TOP)/lib/dmthread +LIBDMTHREAD = $(LIBDMTHREAD_DIR)/$(VARIANT)/libdmthread.a + +LIBRX_DIR = $(MAKE_TOP)/lib/rx +LIBRX = $(LIBRX_DIR)/$(VARIANT)/librx.a + diff --git a/usr/src/make_src/Make/lib/Makefile b/usr/src/make_src/Make/lib/Makefile new file mode 100644 index 0000000..0e0d489 --- /dev/null +++ b/usr/src/make_src/Make/lib/Makefile @@ -0,0 +1,39 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.8 06/12/12 +# +# @(#)Makefile 1.4 96/03/16 SMI + +TOP = ../.. + +SUBDIRS = \ + makestate \ + bsd \ + dmrxm \ + dmrxs \ + mksdmsi18n \ + mksh \ + vroot + +include $(TOP)/rules/recurse.mk diff --git a/usr/src/make_src/Make/lib/bsd/Makefile b/usr/src/make_src/Make/lib/bsd/Makefile new file mode 100644 index 0000000..fd663cd --- /dev/null +++ b/usr/src/make_src/Make/lib/bsd/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.5 06/12/12 +# + +TOP = ../../.. +include $(TOP)/rules/variant.mk +include $(TOP)/rules/derived.mk diff --git a/usr/src/make_src/Make/lib/bsd/src/Makefile b/usr/src/make_src/Make/lib/bsd/src/Makefile new file mode 100644 index 0000000..299c46d --- /dev/null +++ b/usr/src/make_src/Make/lib/bsd/src/Makefile @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.3 06/12/12 +# + +# Generic makefile for use in src directories. Knows how to make common things +# in the right $(VARIANT) directory. + +include $(TOP)/rules/variant.mk + +all := TARG = all +install := TARG = install +clean := TARG = clean +test := TARG = test +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +SRC = ../src +MFLAGS += SRC=$(SRC) + +# See $(TOP)/rules/master.mk for how these are built. +%.h %.cc %.C %.E %.o all install clean test l10n_install i18n_install: FRC + @ if [ ! -d ../$(VARIANT) ]; then \ + mkdir ../$(VARIANT) ; \ + fi + cd ../$(VARIANT); $(MAKE) $(MFLAGS) -f $(SRC)/Variant.mk DESTDIR=$(DESTDIR) $@ + +FRC: diff --git a/usr/src/make_src/Make/lib/bsd/src/Variant.mk b/usr/src/make_src/Make/lib/bsd/src/Variant.mk new file mode 100644 index 0000000..650ee3e --- /dev/null +++ b/usr/src/make_src/Make/lib/bsd/src/Variant.mk @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Variant.mk 1.13 06/12/12 +# + +TOP = ../../../.. +include ${TOP}/rules/master.mk + +PKG_TOP = $(TOP)/Make +CPPFLAGS += -I${PKG_TOP}/include +MSG_FILE = libbsd.msg +I18N_DIRS = $(SRC) + +CCSRCS = bsd.cc +CSRCS = + +HDRS_DIR = ${PKG_TOP}/include/bsd + +.INIT: ${HDRS_DIR}/bsd.h + +LIBNAME = libbsd.a + +include ${TOP}/rules/lib.mk + diff --git a/usr/src/make_src/Make/lib/bsd/src/bsd.cc b/usr/src/make_src/Make/lib/bsd/src/bsd.cc new file mode 100644 index 0000000..c61bca2 --- /dev/null +++ b/usr/src/make_src/Make/lib/bsd/src/bsd.cc @@ -0,0 +1,182 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)bsd.cc 1.6 06/12/12 + */ + +#pragma ident "@(#)bsd.cc 1.6 06/12/12" + +#include <signal.h> + +#include <bsd/bsd.h> + +/* External references. + */ + +/* Forward references. + */ + +/* Static data. + */ + +extern SIG_PF +bsd_signal (int Signal, SIG_PF Handler) +{ + auto SIG_PF previous_handler; +#ifdef SUN5_0 +#ifdef sun + previous_handler = sigset (Signal, Handler); +#else + auto struct sigaction new_action; + auto struct sigaction old_action; + + new_action.sa_flags = SA_SIGINFO; + new_action.sa_handler = (void (*) ()) Handler; + (void) sigemptyset (&new_action.sa_mask); + (void) sigaddset (&new_action.sa_mask, Signal); + + (void) sigaction (Signal, &new_action, &old_action); + + previous_handler = (SIG_PF) old_action.sa_handler; +#endif +#elif defined(linux) + previous_handler = sigset (Signal, Handler); +#else + previous_handler = signal (Signal, Handler); +#endif + return previous_handler; +} + +extern void +bsd_signals (void) +{ + static int initialized = 0; + + if (initialized == 0) + { + initialized = 1; +#if !defined(SUN5_0) && !defined(linux) +#if defined(SIGHUP) + (void) bsd_signal (SIGHUP, SIG_DFL); +#endif +#if defined(SIGINT) + (void) bsd_signal (SIGINT, SIG_DFL); +#endif +#if defined(SIGQUIT) + (void) bsd_signal (SIGQUIT, SIG_DFL); +#endif +#if defined(SIGILL) + (void) bsd_signal (SIGILL, SIG_DFL); +#endif +#if defined(SIGTRAP) + (void) bsd_signal (SIGTRAP, SIG_DFL); +#endif +#if defined(SIGIOT) + (void) bsd_signal (SIGIOT, SIG_DFL); +#endif +#if defined(SIGABRT) + (void) bsd_signal (SIGABRT, SIG_DFL); +#endif +#if defined(SIGEMT) + (void) bsd_signal (SIGEMT, SIG_DFL); +#endif +#if defined(SIGFPE) + (void) bsd_signal (SIGFPE, SIG_DFL); +#endif +#if defined(SIGBUS) + (void) bsd_signal (SIGBUS, SIG_DFL); +#endif +#if defined(SIGSEGV) + (void) bsd_signal (SIGSEGV, SIG_DFL); +#endif +#if defined(SIGSYS) + (void) bsd_signal (SIGSYS, SIG_DFL); +#endif +#if defined(SIGPIPE) + (void) bsd_signal (SIGPIPE, SIG_DFL); +#endif +#if defined(SIGALRM) + (void) bsd_signal (SIGALRM, SIG_DFL); +#endif +#if defined(SIGTERM) + (void) bsd_signal (SIGTERM, SIG_DFL); +#endif +#if defined(SIGUSR1) + (void) bsd_signal (SIGUSR1, SIG_DFL); +#endif +#if defined(SIGUSR2) + (void) bsd_signal (SIGUSR2, SIG_DFL); +#endif +#if defined(SIGCLD) + (void) bsd_signal (SIGCLD, SIG_DFL); +#endif +#if defined(SIGCHLD) + (void) bsd_signal (SIGCHLD, SIG_DFL); +#endif +#if defined(SIGPWR) + (void) bsd_signal (SIGPWR, SIG_DFL); +#endif +#if defined(SIGWINCH) + (void) bsd_signal (SIGWINCH, SIG_DFL); +#endif +#if defined(SIGURG) + (void) bsd_signal (SIGURG, SIG_DFL); +#endif +#if defined(SIGIO) + (void) bsd_signal (SIGIO, SIG_DFL); +#else +#if defined(SIGPOLL) + (void) bsd_signal (SIGPOLL, SIG_DFL); +#endif +#endif +#if defined(SIGTSTP) + (void) bsd_signal (SIGTSTP, SIG_DFL); +#endif +#if defined(SIGCONT) + (void) bsd_signal (SIGCONT, SIG_DFL); +#endif +#if defined(SIGTTIN) + (void) bsd_signal (SIGTTIN, SIG_DFL); +#endif +#if defined(SIGTTOU) + (void) bsd_signal (SIGTTOU, SIG_DFL); +#endif +#if defined(SIGVTALRM) + (void) bsd_signal (SIGVTALRM, SIG_DFL); +#endif +#if defined(SIGPROF) + (void) bsd_signal (SIGPROF, SIG_DFL); +#endif +#if defined(SIGXCPU) + (void) bsd_signal (SIGXCPU, SIG_DFL); +#endif +#if defined(SIGXFSZ) + (void) bsd_signal (SIGXFSZ, SIG_DFL); +#endif +#endif + } + + return; +} diff --git a/usr/src/make_src/Make/lib/makestate/Makefile b/usr/src/make_src/Make/lib/makestate/Makefile new file mode 100644 index 0000000..9c1ddf0 --- /dev/null +++ b/usr/src/make_src/Make/lib/makestate/Makefile @@ -0,0 +1,48 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.7 06/12/12 +# + +TOP = ../../.. +include $(TOP)/rules/variant.mk + +V9_VARIANT :sh= \ +if [ -x /usr/bin/isalist ] ; \ +then \ + for f in `/usr/bin/isalist` ; \ + do \ + if [ "$f" = sparcv9 ] ; \ + then \ + echo sparcv9 ; \ + break ; \ + fi ; \ + if [ "$f" = amd64 ] ; \ + then \ + echo amd64-S2 ; \ + break ; \ + fi ; \ + done ; \ +fi + +include $(TOP)/rules/derived.mk diff --git a/usr/src/make_src/Make/lib/makestate/src/Makefile b/usr/src/make_src/Make/lib/makestate/src/Makefile new file mode 100644 index 0000000..21e239d --- /dev/null +++ b/usr/src/make_src/Make/lib/makestate/src/Makefile @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.5 06/12/12 +# +# @(#)Makefile 1.1 96/03/11 SMI + +# Generic makefile for use in src directories. Knows how to make common things +# in the right $(VARIANT) directory. + +include $(TOP)/rules/variant.mk + +all := TARG = all +install := TARG = install +clean := TARG = clean +test := TARG = test +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +SRC = ../src +MFLAGS += SRC=$(SRC) + +# See $(TOP)/rules/master.mk for how these are built. +%.h %.cc %.C %.E %.o all install clean test l10n_install i18n_install: FRC + @ if [ ! -d ../$(VARIANT) ]; then \ + mkdir ../$(VARIANT) ; \ + fi + cd ../$(VARIANT); $(MAKE) $(MFLAGS) -f $(SRC)/Variant.mk DESTDIR=$(DESTDIR) $@ + +FRC: diff --git a/usr/src/make_src/Make/lib/makestate/src/Variant.mk b/usr/src/make_src/Make/lib/makestate/src/Variant.mk new file mode 100644 index 0000000..26971d5 --- /dev/null +++ b/usr/src/make_src/Make/lib/makestate/src/Variant.mk @@ -0,0 +1,73 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2005 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Variant.mk 1.12 06/12/12 +# + +TOP = ../../../.. + +%.o: $(SRC)/%.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +include $(TOP)/rules/master.mk + +PKG_TOP = $(TOP)/Make + +CSRCS = \ + ld_file.c \ + lock.c + +LIBNAME = libmakestate.a +DLIBNAME = libmakestate.so.1 +MSG_FILE = libmakestate.msg +I18N_DIRS = $(SRC) + +CFLAGS += $(V9FLAGS) -KPIC -DTEXT_DOMAIN=\"SUNW_OST_OSLIB\" +CPPFLAGS= + +#include $(TOP)/Make/lib/Lib.mk +include $(TOP)/rules/lib.mk + +POUND_SIGN:sh= echo \# +RELEASE= 5.11 +VERSION= $(RELEASE_VER) +PATCHID= $(VERSION) +DATE:sh = date '+%B %Y' +RELEASE_DATE= $(DATE) +PATCH_DATE= $(RELEASE_DATE) +RELEASE_CM= "@($(POUND_SIGN))RELEASE VERSION SunOS $(RELEASE) $(PATCHID) $(PATCH_DATE)" + +PROCESS_COMMENT= mcs -a $(RELEASE_CM) +POST_PROCESS_SO= $(PROCESS_COMMENT) $@ + +$(DLIBNAME) : $(LIBNAME) + $(CC) $(V9FLAGS) -o $@ -dy -G -ztext -h $@ ld_file.o lock.o -lelf + mcs -d $@ + ${POST_PROCESS_SO} + +all: $(DLIBNAME) + +install: all + ${INSTALL} -d ${DESTDIR}/usr/lib$(VAR_DIR) + ${RM} ${DESTDIR}/usr/lib$(VAR_DIR)/$(DLIBNAME) + ${INSTALL} $(DLIBNAME) ${DESTDIR}/usr/lib$(VAR_DIR) diff --git a/usr/src/make_src/Make/lib/makestate/src/ld_file.c b/usr/src/make_src/Make/lib/makestate/src/ld_file.c new file mode 100644 index 0000000..b80ea68 --- /dev/null +++ b/usr/src/make_src/Make/lib/makestate/src/ld_file.c @@ -0,0 +1,192 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1998 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)ld_file.c 1.7 06/12/12 + */ +#pragma ident "@(#)ld_file.c 1.7 06/12/12" + +#pragma init(ld_support_init) + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <libelf.h> +#include <sys/param.h> +#include <link.h> + +#define SUNPRO_DEPENDENCIES "SUNPRO_DEPENDENCIES" + +/* + * Linked list of strings - used to keep lists of names + * of directories or files. + */ + +struct Stritem { + char * str; + void * next; +}; + +typedef struct Stritem Stritem; + +static char * depend_file = NULL; +static Stritem * list = NULL; + + +void mk_state_init() +{ + depend_file = getenv(SUNPRO_DEPENDENCIES); +} /* mk_state_init() */ + + + +static void +prepend_str(Stritem **list, const char * str) +{ + Stritem * new; + char * newstr; + + if (!(new = calloc(1, sizeof (Stritem)))) { + perror("libmakestate.so"); + return; + } /* if */ + + if (!(newstr = malloc(strlen(str) + 1))) { + perror("libmakestate.so"); + return; + } /* if */ + + new->str = strcpy(newstr, str); + new->next = *list; + *list = new; + +} /* prepend_str() */ + + +void +mk_state_collect_dep(const char * file) +{ + /* + * SUNPRO_DEPENDENCIES wasn't set, we don't collect .make.state + * information. + */ + if (!depend_file) + return; + + prepend_str(&list, file); + +} /* mk_state_collect_dep() */ + + +void +mk_state_update_exit() +{ + Stritem * cur; + char lockfile[MAXPATHLEN], * err, * space, * target; + FILE * ofp; + extern char * file_lock(char *, char *, int); + + if (!depend_file) + return; + + if ((space = strchr(depend_file, ' ')) == NULL) + return; + *space = '\0'; + target = &space[1]; + + (void) sprintf(lockfile, "%s.lock", depend_file); + if ((err = file_lock(depend_file, lockfile, 0))) { + (void) fprintf(stderr, "%s\n", err); + return; + } /* if */ + + if (!(ofp = fopen(depend_file, "a"))) + return; + + if (list) + (void) fprintf(ofp, "%s: ", target); + + for (cur = list; cur; cur = cur->next) + (void) fprintf(ofp, " %s", cur->str); + + (void) fputc('\n', ofp); + + (void) fclose(ofp); + (void) unlink(lockfile); + *space = ' '; + +} /* mk_state_update_exit() */ + +static void +/* LINTED static unused */ +ld_support_init() +{ + mk_state_init(); + +} /* ld_support_init() */ + +/* ARGSUSED */ +void +ld_file(const char * file, const Elf_Kind ekind, int flags, Elf *elf) +{ + if(! ((flags & LD_SUP_DERIVED) && !(flags & LD_SUP_EXTRACTED))) + return; + + mk_state_collect_dep(file); + +} /* ld_file */ + +void +ld_atexit(int exit_code) +{ + if (exit_code) + return; + + mk_state_update_exit(); + +} /* ld_atexit() */ + +/* + * Supporting 64-bit objects + */ +void +ld_file64(const char * file, const Elf_Kind ekind, int flags, Elf *elf) +{ + if(! ((flags & LD_SUP_DERIVED) && !(flags & LD_SUP_EXTRACTED))) + return; + + mk_state_collect_dep(file); + +} /* ld_file64 */ + +void +ld_atexit64(int exit_code) +{ + if (exit_code) + return; + + mk_state_update_exit(); + +} /* ld_atexit64() */ diff --git a/usr/src/make_src/Make/lib/makestate/src/lock.c b/usr/src/make_src/Make/lib/makestate/src/lock.c new file mode 100644 index 0000000..7646059 --- /dev/null +++ b/usr/src/make_src/Make/lib/makestate/src/lock.c @@ -0,0 +1,175 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)lock.c 1.5 06/12/12 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/errno.h> +#include <errno.h> /* errno */ + +#if defined(_LP64) +/* + * The symbols _sys_errlist and _sys_nerr are not visible in the + * LP64 libc. Use strerror(3C) instead. + */ +#else /* #_LP64 */ +extern char * sys_errlist[]; +extern int sys_nerr; +#endif /* #_LP64 */ + +static void file_lock_error(); + +/* + * This code stolen from the NSE library and changed to not depend + * upon any NSE routines or header files. + * + * Simple file locking. + * Create a symlink to a file. The "test and set" will be + * atomic as creating the symlink provides both functions. + * + * The timeout value specifies how long to wait for stale locks + * to disappear. If the lock is more than 'timeout' seconds old + * then it is ok to blow it away. This part has a small window + * of vunerability as the operations of testing the time, + * removing the lock and creating a new one are not atomic. + * It would be possible for two processes to both decide to blow + * away the lock and then have process A remove the lock and establish + * its own, and then then have process B remove the lock which accidentily + * removes A's lock rather than the stale one. + * + * A further complication is with the NFS. If the file in question is + * being served by an NFS server, then its time is set by that server. + * We can not use the time on the client machine to check for a stale + * lock. Therefore, a temp file on the server is created to get + * the servers current time. + * + * Returns an error message. NULL return means the lock was obtained. + * + */ +char * +file_lock(char * name, char * lockname, int timeout) +{ + int r; + int fd; + struct stat statb; + struct stat fs_statb; + char tmpname[MAXPATHLEN]; + static char msg[MAXPATHLEN]; + + if (timeout <= 0) { + timeout = 15; + } + for (;;) { + r = symlink(name, lockname); + if (r == 0) { + return (NULL); + } + if (errno != EEXIST) { + file_lock_error(msg, name, + (const char *)"symlink(%s, %s)", name, lockname); + return (msg); + } + for (;;) { + (void) sleep(1); + r = lstat(lockname, &statb); + if (r == -1) { + /* + * The lock must have just gone away - try + * again. + */ + break; + } + + /* + * With the NFS the time given a file is the time on + * the file server. This time may vary from the + * client's time. Therefore, we create a tmpfile in + * the same directory to establish the time on the + * server and use this time to see if the lock has + * expired. + */ + (void) sprintf(tmpname, "%s.XXXXXX", lockname); + (void) mktemp(tmpname); + fd = creat(tmpname, 0666); + if (fd != -1) { + (void) close(fd); + } else { + file_lock_error(msg, name, + (const char *)"creat(%s)", tmpname); + return (msg); + } + if (stat(tmpname, &fs_statb) == -1) { + file_lock_error(msg, name, + (const char *)"stat(%s)", tmpname); + return (msg); + } + (void) unlink(tmpname); + if (statb.st_mtime + timeout < fs_statb.st_mtime) { + /* + * The lock has expired - blow it away. + */ + (void) unlink(lockname); + break; + } + } + } + /* NOTREACHED */ +} + +/* + * Format a message telling why the lock could not be created. + */ +/* VARARGS4 */ +static void +file_lock_error(char * msg, char * file, const char * str, char * arg1, + char * arg2) +{ + int len; + + (void) sprintf(msg, "Could not lock file `%s'; ", file); + len = strlen(msg); + (void) sprintf(&msg[len], str, arg1, arg2); + (void) strcat(msg, " failed - "); +#if defined(_LP64) + /* Needs to be changed to use strerror(3C) instead. */ + len = strlen(msg); + (void) sprintf(&msg[len], "errno %d", errno); +#else /* #_LP64 */ + if (errno < sys_nerr) { + (void) strcat(msg, sys_errlist[errno]); + } else { + len = strlen(msg); + (void) sprintf(&msg[len], "errno %d", errno); + } +#endif /* #_LP64 */ +} diff --git a/usr/src/make_src/Make/lib/mksdmsi18n/Makefile b/usr/src/make_src/Make/lib/mksdmsi18n/Makefile new file mode 100644 index 0000000..c9d8161 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksdmsi18n/Makefile @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.5 06/12/12 +# + +TOP = ../../.. +include $(TOP)/rules/variant.mk +include $(TOP)/rules/derived.mk + diff --git a/usr/src/make_src/Make/lib/mksdmsi18n/src/Makefile b/usr/src/make_src/Make/lib/mksdmsi18n/src/Makefile new file mode 100644 index 0000000..f27801b --- /dev/null +++ b/usr/src/make_src/Make/lib/mksdmsi18n/src/Makefile @@ -0,0 +1,46 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.10 06/12/12 +# + +TOP = ../../../.. +include $(TOP)/rules/master.mk + +SUBDIRS = lib +include $(TOP)/rules/recurse.mk +include $(SRC)/lib/version.mk + +PKG_TOP = $(TOP)/Make +CPPFLAGS += -I$(PKG_TOP)/include + +CCSRCS = libmksdmsi18n_init.cc + +LIBNAME = libmksdmsi18n.a + +# +# Pass in the version number for the i18n message catalog. +# +libmksdmsi18n_init.o := CPPFLAGS += -DI18N_VERSION=$(VERSION) + +include $(TOP)/rules/lib.mk diff --git a/usr/src/make_src/Make/lib/mksdmsi18n/src/Variant.mk b/usr/src/make_src/Make/lib/mksdmsi18n/src/Variant.mk new file mode 100644 index 0000000..1faef99 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksdmsi18n/src/Variant.mk @@ -0,0 +1,52 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1997 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Variant.mk 1.4 06/12/12 +# + +TOP = ../../../.. +include $(TOP)/rules/master.mk +#include $(TOP)/rules/dmake.mk + +#SUBDIRS = $(SRC)/lib +#include $(TOP)/rules/recurse.mk + +CCSRCS = \ + libmksdmsi18n_init.cc + +CSRCS = + +include $(SRC)/lib/version.mk + +libmksdmsi18n_init.o := CPPFLAGS += -DI18N_VERSION=$(VERSION) + +#PKG_TOP = $(TOP)/Make +#CPPFLAGS += -I$(PKG_TOP)/include + +LIBNAME = libmksdmsi18n.a +MSG_FILE = libmksdmsi18n.msg +I18N_DIRS = $(SRC) + +include $(TOP)/Make/lib/Lib.mk +include $(TOP)/rules/lib.mk + diff --git a/usr/src/make_src/Make/lib/mksdmsi18n/src/lib/Makefile b/usr/src/make_src/Make/lib/mksdmsi18n/src/lib/Makefile new file mode 100644 index 0000000..73399b1 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksdmsi18n/src/lib/Makefile @@ -0,0 +1,54 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.7 06/12/12 +# + +include version.mk + +TOP = ../../../../.. +PKG_TOP = $(TOP)/Make +PKG_LIB_TOP = $(PKG_TOP)/lib +I18N_LIBS = bsd dmrxm dmrxs mksh vroot +I18N_DIRS = $(I18N_LIBS:%=$(PKG_LIB_TOP)/%/src) +SRC = . +APPPATH = . +LIBNAME = libmksdmsi18n +TEXTDOMAIN = $(LIBNAME)_$(VERSION) +MSG_FILE = $(TEXTDOMAIN).msg + +all clean: +install: catalogs .WAIT i18n_install + +# +# This is a hack until the top level makefiles for i18n/l10n message catalogs +# are better organized and written. +# This "catalogs" target was cp'ed from $(TOP)/rules/lib.mk +# +catalogs: + $(GENMSG) -l $(SRC)/genmsg.project -o $(MSG_FILE) `find $(I18N_DIRS) \( -name '*.cc' -o -name '*.c' -o -name '*.y' \) -print | grep -v /SCCS/` + rm -f *.cc.new + +include $(PKG_TOP)/prodver.mk +include $(TOP)/rules/i18n-install.mk + diff --git a/usr/src/make_src/Make/lib/mksdmsi18n/src/lib/version.mk b/usr/src/make_src/Make/lib/mksdmsi18n/src/lib/version.mk new file mode 100644 index 0000000..aaad8d8 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksdmsi18n/src/lib/version.mk @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1995 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)version.mk 1.2 06/12/12 +# + +# A version number is needed to version the i18n catalog file + +VERSION = 1 + diff --git a/usr/src/make_src/Make/lib/mksdmsi18n/src/libmksdmsi18n_init.cc b/usr/src/make_src/Make/lib/mksdmsi18n/src/libmksdmsi18n_init.cc new file mode 100644 index 0000000..e234125 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksdmsi18n/src/libmksdmsi18n_init.cc @@ -0,0 +1,63 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1996 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)libmksdmsi18n_init.cc 1.5 06/12/12 + */ + +#pragma ident "@(#)libmksdmsi18n_init.cc 1.5 06/12/12" + +#include <avo/intl.h> +#include <stdio.h> +#include <stdlib.h> + +nl_catd libmksdmsi18n_catd; + +/* + * Open the catalog file for libmksdmsi18n. Users of this library must set + * NSLPATH first. See avo_18n_init(). + */ +int +libmksdmsi18n_init() +{ + char name[20]; + + if (getenv(NOCATGETS("NLSPATH")) == NULL) { + fprintf(stderr, NOCATGETS("Internal error: Set NLSPATH before opening catalogue file\n")); + return 1; + } + sprintf(name, NOCATGETS("libmksdmsi18n_%d"), I18N_VERSION); + libmksdmsi18n_catd = catopen(name, NL_CAT_LOCALE); + return 0; +} + +/* + * Close the catalog file for libmksdmsi18n + */ +void +libmksdmsi18n_fini() +{ + catclose(libmksdmsi18n_catd); +} + diff --git a/usr/src/make_src/Make/lib/mksh/Makefile b/usr/src/make_src/Make/lib/mksh/Makefile new file mode 100644 index 0000000..fd663cd --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.5 06/12/12 +# + +TOP = ../../.. +include $(TOP)/rules/variant.mk +include $(TOP)/rules/derived.mk diff --git a/usr/src/make_src/Make/lib/mksh/src/Makefile b/usr/src/make_src/Make/lib/mksh/src/Makefile new file mode 100644 index 0000000..ebed78f --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/Makefile @@ -0,0 +1,50 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.3 06/12/12 +# + +# Generic makefile for use in src directories. Knows how to make common things +# in the right $(VARIANT) directory. + +#TOP = ../../../.. +include $(TOP)/rules/variant.mk + +all := TARG = all +install := TARG = install +clean := TARG = clean +test := TARG = test +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +SRC = ../src +MFLAGS += SRC=$(SRC) + +# See $(TOP)/rules/master.mk for how these are built. +%.h %.cc %.C %.E %.o all install clean test l10n_install i18n_install: FRC + @ if [ ! -d ../$(VARIANT) ]; then \ + mkdir ../$(VARIANT) ; \ + fi + cd ../$(VARIANT); $(MAKE) $(MFLAGS) -f $(SRC)/Variant.mk DESTDIR=$(DESTDIR) $@ + +FRC: diff --git a/usr/src/make_src/Make/lib/mksh/src/Variant.mk b/usr/src/make_src/Make/lib/mksh/src/Variant.mk new file mode 100644 index 0000000..427ba54 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/Variant.mk @@ -0,0 +1,58 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Variant.mk 1.19 06/12/12 +# + +TOP = ../../../.. +include $(TOP)/rules/master.mk +include $(TOP)/rules/dmake.mk + +PKG_TOP = $(TOP)/Make +CPPFLAGS += -I$(PKG_TOP)/include + +CCSRCS = \ + dosys.cc \ + globals.cc \ + i18n.cc \ + macro.cc \ + misc.cc \ + mksh.cc \ + read.cc + +HDRS_DIR = $(PKG_TOP)/include/mksh +HDRS_LIST = $(HDRS_DIR)/defs.h \ + $(CCSRCS:%.cc=$(HDRS_DIR)/%.h) \ + $(CSRCS:%.c=$(HDRS_DIR)/%.h) + +.INIT: $(HDRS_LIST) + +LIBNAME = libmksh.a +MSG_FILE = libmksh.msg +I18N_DIRS = $(SRC) + +#CPPFLAGS += -DTEAMWARE_MAKE_CMN -DDISTRIBUTED + +include $(TOP)/Make/lib/Lib.mk +include $(TOP)/rules/lib.mk + diff --git a/usr/src/make_src/Make/lib/mksh/src/dosys.cc b/usr/src/make_src/Make/lib/mksh/src/dosys.cc new file mode 100644 index 0000000..fc4306b --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/dosys.cc @@ -0,0 +1,851 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)dosys.cc 1.38 06/12/12 + */ + +#pragma ident "@(#)dosys.cc 1.38 06/12/12" + +/* + * dosys.cc + * + * Execute one commandline + */ + +/* + * Included files + */ +#include <sys/wait.h> /* WIFEXITED(status) */ +#include <avo/avo_alloca.h> /* alloca() */ + +#if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) /* tolik */ +# include <avo/strings.h> /* AVO_STRDUP() */ +#if defined(DISTRIBUTED) +# include <dm/Avo_CmdOutput.h> +# include <rw/xdrstrea.h> +#endif +#endif + +#include <stdio.h> /* errno */ +#include <errno.h> /* errno */ +#include <fcntl.h> /* open() */ +#include <mksh/dosys.h> +#include <mksh/macro.h> /* getvar() */ +#include <mksh/misc.h> /* getmem(), fatal_mksh(), errmsg() */ +#include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */ +#include <sys/signal.h> /* SIG_DFL */ +#include <sys/stat.h> /* open() */ +#include <sys/wait.h> /* wait() */ +#include <ulimit.h> /* ulimit() */ +#include <unistd.h> /* close(), dup2() */ + +#if defined (HP_UX) || defined (linux) +# include <sys/param.h> +# include <wctype.h> +# include <wchar.h> +#endif + +#if defined (linux) +# define wslen(x) wcslen(x) +# define wscpy(x,y) wcscpy(x,y) +#endif + +/* + * Defined macros + */ +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +#define SEND_MTOOL_MSG(cmds) \ + if (send_mtool_msgs) { \ + cmds \ + } +#else +#define SEND_MTOOL_MSG(cmds) +#endif + +/* + * typedefs & structs + */ + +/* + * Static variables + */ + +/* + * File table of contents + */ +static Boolean exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path); + +/* + * Workaround for NFS bug. Sometimes, when running 'open' on a remote + * dmake server, it fails with "Stale NFS file handle" error. + * The second attempt seems to work. + */ +int +my_open(const char *path, int oflag, mode_t mode) { + int res = open(path, oflag, mode); +#ifdef linux +// Workaround for NFS problem: even when all directories in 'path' +// exist, 'open' (file creation) fails with ENOENT. + int nattempt = 0; + while (res < 0 && (errno == ESTALE || errno == EAGAIN || errno == ENOENT)) { + nattempt++; + if(nattempt > 30) { + break; + } + sleep(1); +#else + if (res < 0 && (errno == ESTALE || errno == EAGAIN)) { +#endif + /* Stale NFS file handle. Try again */ + res = open(path, oflag, mode); + } + return res; +} + +/* + * void + * redirect_io(char *stdout_file, char *stderr_file) + * + * Redirects stdout and stderr for a child mksh process. + */ +void +redirect_io(char *stdout_file, char *stderr_file) +{ + long descriptor_limit; + int i; + +#if defined (HP_UX) || defined (linux) + /* + * HP-UX does not support the UL_GDESLIM command for ulimit(). + * NOFILE == max num open files per process (from <sys/param.h>) + */ + descriptor_limit = NOFILE; +#else + if ((descriptor_limit = ulimit(UL_GDESLIM)) < 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 89, "ulimit() failed: %s"), errmsg(errno)); + } +#endif + for (i = 3; i < descriptor_limit; i++) { + (void) close(i); + } + if ((i = my_open(stdout_file, + O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC, + S_IREAD | S_IWRITE)) < 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 90, "Couldn't open standard out temp file `%s': %s"), + stdout_file, + errmsg(errno)); + } else { + if (dup2(i, 1) == -1) { + fatal_mksh(NOCATGETS("*** Error: dup2(3, 1) failed: %s"), + errmsg(errno)); + } + close(i); + } + if (stderr_file == NULL) { + if (dup2(1, 2) == -1) { + fatal_mksh(NOCATGETS("*** Error: dup2(1, 2) failed: %s"), + errmsg(errno)); + } + } else if ((i = my_open(stderr_file, + O_WRONLY | O_CREAT | O_TRUNC | O_DSYNC, + S_IREAD | S_IWRITE)) < 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 91, "Couldn't open standard error temp file `%s': %s"), + stderr_file, + errmsg(errno)); + } else { + if (dup2(i, 2) == -1) { + fatal_mksh(NOCATGETS("*** Error: dup2(3, 2) failed: %s"), + errmsg(errno)); + } + close(i); + } +} + +/* + * dosys_mksh(command, ignore_error, call_make, silent_error, target) + * + * Check if command string contains meta chars and dispatch to + * the proper routine for executing one command line. + * + * Return value: + * Indicates if the command execution failed + * + * Parameters: + * command The command to run + * ignore_error Should we abort when an error is seen? + * call_make Did command reference $(MAKE) ? + * silent_error Should error messages be suppressed for dmake? + * target Target we are building + * + * Global variables used: + * do_not_exec_rule Is -n on? + * working_on_targets We started processing real targets + */ +Doname +dosys_mksh(register Name command, register Boolean ignore_error, register Boolean call_make, Boolean silent_error, Boolean always_exec, Name target, Boolean redirect_out_err, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio) +{ + register int length = command->hash.length; + register wchar_t *p; + register wchar_t *q; + register wchar_t *cmd_string; + struct stat before; + Doname result; + Boolean working_on_targets_mksh = true; + Wstring wcb(command); + p = wcb.get_string(); + cmd_string = p; + + /* Strip spaces from head of command string */ + while (iswspace(*p)) { + p++, length--; + } + if (*p == (int) nul_char) { + return build_failed; + } + /* If we are faking it we just return */ + if (do_not_exec_rule && + working_on_targets_mksh && + !call_make && + !always_exec) { + return build_ok; + } + + /* Copy string to make it OK to write it. */ + q = ALLOC_WC(length + 1); + (void) wscpy(q, p); + /* Write the state file iff this command uses make. */ +/* XXX - currently does not support recursive make's, $(MAKE)'s + if (call_make && command_changed) { + write_state_file(0, false); + } + (void) stat(make_state->string_mb, &before); + */ + /* + * Run command directly if it contains no shell meta chars, + * else run it using the shell. + */ + /* XXX - command->meta *may* not be set correctly */ + if (await(ignore_error, + silent_error, + target, + cmd_string, + command->meta ? + doshell(q, ignore_error, redirect_out_err, stdout_file, stderr_file, nice_prio) : + doexec(q, ignore_error, redirect_out_err, stdout_file, stderr_file, vroot_path, nice_prio), + false, + NULL, + -1)) { + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in dosys_mksh(), and await() returned result of build_ok.")); +#endif + + result = build_ok; + } else { + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in dosys_mksh(), and await() returned result of build_failed.")); +#endif + + result = build_failed; + } + retmem(q); + +/* XXX - currently does not support recursive make's, $(MAKE)'s + if ((report_dependencies_level == 0) && + call_make) { + make_state->stat.time = (time_t)file_no_time; + (void)exists(make_state); + if (before.st_mtime == make_state->stat.time) { + return result; + } + makefile_type = reading_statefile; + if (read_trace_level > 1) { + trace_reader = true; + } + (void) read_simple_file(make_state, + false, + false, + false, + false, + false, + true); + trace_reader = false; + } + */ + return result; +} + +/* + * doshell(command, ignore_error) + * + * Used to run command lines that include shell meta-characters. + * The make macro SHELL is supposed to contain a path to the shell. + * + * Return value: + * The pid of the process we started + * + * Parameters: + * command The command to run + * ignore_error Should we abort on error? + * + * Global variables used: + * filter_stderr If -X is on we redirect stderr + * shell_name The Name "SHELL", used to get the path to shell + */ +int +doshell(wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, int nice_prio) +{ + char *argv[6]; + int argv_index = 0; + int cmd_argv_index; + int length; + char nice_prio_buf[MAXPATHLEN]; + register Name shell = getvar(shell_name); + register char *shellname; + char *tmp_mbs_buffer; + + + if (IS_EQUAL(shell->string_mb, "")) { + shell = shell_name; + } + if ((shellname = strrchr(shell->string_mb, (int) slash_char)) == NULL) { + shellname = shell->string_mb; + } else { + shellname++; + } + + /* + * Only prepend the /usr/bin/nice command to the original command + * if the nice priority, nice_prio, is NOT zero (0). + * Nice priorities can be a positive or a negative number. + */ + if (nice_prio != 0) { + argv[argv_index++] = NOCATGETS("nice"); + (void) sprintf(nice_prio_buf, NOCATGETS("-%d"), nice_prio); + argv[argv_index++] = strdup(nice_prio_buf); + } + argv[argv_index++] = shellname; +#if defined(linux) + if(0 == strcmp(shell->string_mb, (char*)NOCATGETS("/bin/sh"))) { + argv[argv_index++] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce")); + } else { + argv[argv_index++] = (char*)NOCATGETS("-c"); + } +#else + argv[argv_index++] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce")); +#endif + if ((length = wslen(command)) >= MAXPATHLEN) { + tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1); + (void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1); + cmd_argv_index = argv_index; + argv[argv_index++] = strdup(tmp_mbs_buffer); + retmem_mb(tmp_mbs_buffer); + } else { + WCSTOMBS(mbs_buffer, command); + cmd_argv_index = argv_index; +#if defined(linux) + int mbl = strlen(mbs_buffer); + if(mbl > 2) { + if(mbs_buffer[mbl-1] == '\n' && mbs_buffer[mbl-2] == '\\') { + mbs_buffer[mbl] = '\n'; + mbs_buffer[mbl+1] = 0; + } + } +#endif + argv[argv_index++] = strdup(mbs_buffer); + } + argv[argv_index] = NULL; + (void) fflush(stdout); + if ((childPid = fork()) == 0) { + enable_interrupt((void (*) (int)) SIG_DFL); + if (redirect_out_err) { + redirect_io(stdout_file, stderr_file); + } +#if 0 + if (filter_stderr) { + redirect_stderr(); + } +#endif + if (nice_prio != 0) { + (void) execve(NOCATGETS("/usr/bin/nice"), argv, environ); + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 92, "Could not load `/usr/bin/nice': %s"), + errmsg(errno)); + } else { + (void) execve(shell->string_mb, argv, environ); + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 93, "Could not load Shell from `%s': %s"), + shell->string_mb, + errmsg(errno)); + } + } + if (childPid == -1) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 94, "fork failed: %s"), + errmsg(errno)); + } + retmem_mb(argv[cmd_argv_index]); + return childPid; +} + +/* + * exec_vp(name, argv, envp, ignore_error) + * + * Like execve, but does path search. + * This starts command when make invokes it directly (without a shell). + * + * Return value: + * Returns false if the exec failed + * + * Parameters: + * name The name of the command to run + * argv Arguments for the command + * envp The environment for it + * ignore_error Should we abort on error? + * + * Global variables used: + * shell_name The Name "SHELL", used to get the path to shell + * vroot_path The path used by the vroot package + */ +static Boolean +exec_vp(register char *name, register char **argv, char **envp, register Boolean ignore_error, pathpt vroot_path) +{ + register Name shell = getvar(shell_name); + register char *shellname; + char *shargv[4]; + Name tmp_shell; + + if (IS_EQUAL(shell->string_mb, "")) { + shell = shell_name; + } + + for (int i = 0; i < 5; i++) { + (void) execve_vroot(name, + argv + 1, + envp, + vroot_path, + VROOT_DEFAULT); + switch (errno) { + case ENOEXEC: + case ENOENT: + /* That failed. Let the shell handle it */ + shellname = strrchr(shell->string_mb, (int) slash_char); + if (shellname == NULL) { + shellname = shell->string_mb; + } else { + shellname++; + } + shargv[0] = shellname; + shargv[1] = (char*)(ignore_error ? NOCATGETS("-c") : NOCATGETS("-ce")); + shargv[2] = argv[0]; + shargv[3] = NULL; + tmp_shell = getvar(shell_name); + if (IS_EQUAL(tmp_shell->string_mb, "")) { + tmp_shell = shell_name; + } + (void) execve_vroot(tmp_shell->string_mb, + shargv, + envp, + vroot_path, + VROOT_DEFAULT); + return failed; + case ETXTBSY: + /* + * The program is busy (debugged?). + * Wait and then try again. + */ + (void) sleep((unsigned) i); + case EAGAIN: + break; + default: + return failed; + } + } + return failed; +} + +/* + * doexec(command, ignore_error) + * + * Will scan an argument string and split it into words + * thus building an argument list that can be passed to exec_ve() + * + * Return value: + * The pid of the process started here + * + * Parameters: + * command The command to run + * ignore_error Should we abort on error? + * + * Global variables used: + * filter_stderr If -X is on we redirect stderr + */ +int +doexec(register wchar_t *command, register Boolean ignore_error, Boolean redirect_out_err, char *stdout_file, char *stderr_file, pathpt vroot_path, int nice_prio) +{ + int arg_count = 5; + char **argv; + int length; + char nice_prio_buf[MAXPATHLEN]; + register char **p; + wchar_t *q; + register wchar_t *t; + char *tmp_mbs_buffer; + + /* + * Only prepend the /usr/bin/nice command to the original command + * if the nice priority, nice_prio, is NOT zero (0). + * Nice priorities can be a positive or a negative number. + */ + if (nice_prio != 0) { + arg_count += 2; + } + for (t = command; *t != (int) nul_char; t++) { + if (iswspace(*t)) { + arg_count++; + } + } + argv = (char **)alloca(arg_count * (sizeof(char *))); + /* + * Reserve argv[0] for sh in case of exec_vp failure. + * Don't worry about prepending /usr/bin/nice command to argv[0]. + * In fact, doing it may cause the sh command to fail! + */ + p = &argv[1]; + if ((length = wslen(command)) >= MAXPATHLEN) { + tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1); + (void) wcstombs(tmp_mbs_buffer, command, (length * MB_LEN_MAX) + 1); + argv[0] = strdup(tmp_mbs_buffer); + retmem_mb(tmp_mbs_buffer); + } else { + WCSTOMBS(mbs_buffer, command); + argv[0] = strdup(mbs_buffer); + } + + if (nice_prio != 0) { + *p++ = strdup(NOCATGETS("/usr/bin/nice")); + (void) sprintf(nice_prio_buf, NOCATGETS("-%d"), nice_prio); + *p++ = strdup(nice_prio_buf); + } + /* Build list of argument words. */ + for (t = command; *t;) { + if (p >= &argv[arg_count]) { + /* This should never happen, right? */ + WCSTOMBS(mbs_buffer, command); + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 95, "Command `%s' has more than %d arguments"), + mbs_buffer, + arg_count); + } + q = t; + while (!iswspace(*t) && (*t != (int) nul_char)) { + t++; + } + if (*t) { + for (*t++ = (int) nul_char; iswspace(*t); t++); + } + if ((length = wslen(q)) >= MAXPATHLEN) { + tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1); + (void) wcstombs(tmp_mbs_buffer, q, (length * MB_LEN_MAX) + 1); + *p++ = strdup(tmp_mbs_buffer); + retmem_mb(tmp_mbs_buffer); + } else { + WCSTOMBS(mbs_buffer, q); + *p++ = strdup(mbs_buffer); + } + } + *p = NULL; + + /* Then exec the command with that argument list. */ + (void) fflush(stdout); + if ((childPid = fork()) == 0) { + enable_interrupt((void (*) (int)) SIG_DFL); + if (redirect_out_err) { + redirect_io(stdout_file, stderr_file); + } +#if 0 + if (filter_stderr) { + redirect_stderr(); + } +#endif + (void) exec_vp(argv[1], argv, environ, ignore_error, vroot_path); + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 96, "Cannot load command `%s': %s"), argv[1], errmsg(errno)); + } + if (childPid == -1) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 97, "fork failed: %s"), + errmsg(errno)); + } + for (int i = 0; argv[i] != NULL; i++) { + retmem_mb(argv[i]); + } + return childPid; +} + +/* + * await(ignore_error, silent_error, target, command, running_pid) + * + * Wait for one child process and analyzes + * the returned status when the child process terminates. + * + * Return value: + * Returns true if commands ran OK + * + * Parameters: + * ignore_error Should we abort on error? + * silent_error Should error messages be suppressed for dmake? + * target The target we are building, for error msgs + * command The command we ran, for error msgs + * running_pid The pid of the process we are waiting for + * + * Static variables used: + * filter_file The fd for the filter file + * filter_file_name The name of the filter file + * + * Global variables used: + * filter_stderr Set if -X is on + */ +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +Boolean +await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, Boolean send_mtool_msgs, XDR *xdrs_p, int job_msg_id) +#else +Boolean +await(register Boolean ignore_error, register Boolean silent_error, Name target, wchar_t *command, pid_t running_pid, Boolean send_mtool_msgs, void *xdrs_p, int job_msg_id) +#endif +{ +#ifdef SUN5_0 + int status; +#else +#ifndef WEXITSTATUS +#define WEXITSTATUS(stat) stat.w_T.w_Retcode +#endif +#ifndef WTERMSIG +#define WTERMSIG(stat) stat.w_T.w_Termsig +#endif +#ifndef WCOREDUMP +#define WCOREDUMP(stat) stat.w_T.w_Coredump +#endif +#if defined (HP_UX) || defined (linux) + int status; +#else + union wait status; +#endif +#endif + char *buffer; + int core_dumped; + int exit_status; +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + Avo_CmdOutput *make_output_msg; +#endif + FILE *outfp; + register pid_t pid; + struct stat stat_buff; + int termination_signal; + char tmp_buf[MAXPATHLEN]; +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ + RWCollectable *xdr_msg; +#endif + + while ((pid = wait(&status)) != running_pid) { + if (pid == -1) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 98, "wait() failed: %s"), errmsg(errno)); + } + } + (void) fflush(stdout); + (void) fflush(stderr); + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + if (status == 0) { + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in await(), and status is 0.")); +#endif + + return succeeded; + } + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in await(), and status is *NOT* 0.")); +#endif + +#else + if (status.w_status == 0) { + return succeeded; + } +#endif + + exit_status = WEXITSTATUS(status); + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in await(), and exit_status is %d."), exit_status); +#endif + + termination_signal = WTERMSIG(status); + core_dumped = WCOREDUMP(status); + + /* + * If the child returned an error, we now try to print a + * nice message about it. + */ + SEND_MTOOL_MSG( + make_output_msg = new Avo_CmdOutput(); + (void) sprintf(tmp_buf, "%d", job_msg_id); + make_output_msg->appendOutput(AVO_STRDUP(tmp_buf)); + ); + + tmp_buf[0] = (int) nul_char; + if (!silent_error) { + if (exit_status != 0) { + (void) fprintf(stdout, + catgets(libmksdmsi18n_catd, 1, 103, "*** Error code %d"), + exit_status); + SEND_MTOOL_MSG( + (void) sprintf(&tmp_buf[strlen(tmp_buf)], + catgets(libmksdmsi18n_catd, 1, 104, "*** Error code %d"), + exit_status); + ); + } else { +#if ! defined(SUN5_0) && ! defined(HP_UX) && ! defined(linux) + if (termination_signal > NSIG) { +#endif + (void) fprintf(stdout, + catgets(libmksdmsi18n_catd, 1, 105, "*** Signal %d"), + termination_signal); + SEND_MTOOL_MSG( + (void) sprintf(&tmp_buf[strlen(tmp_buf)], + catgets(libmksdmsi18n_catd, 1, 106, "*** Signal %d"), + termination_signal); + ); +#if ! defined(SUN5_0) && ! defined(HP_UX) && ! defined(linux) + } else { + (void) fprintf(stdout, + "*** %s", + sys_siglist[termination_signal]); + SEND_MTOOL_MSG( + (void) sprintf(&tmp_buf[strlen(tmp_buf)], + "*** %s", + sys_siglist[termination_signal]); + ); + } +#endif + if (core_dumped) { + (void) fprintf(stdout, + catgets(libmksdmsi18n_catd, 1, 107, " - core dumped")); + SEND_MTOOL_MSG( + (void) sprintf(&tmp_buf[strlen(tmp_buf)], + catgets(libmksdmsi18n_catd, 1, 108, " - core dumped")); + ); + } + } + if (ignore_error) { + (void) fprintf(stdout, + catgets(libmksdmsi18n_catd, 1, 109, " (ignored)")); + SEND_MTOOL_MSG( + (void) sprintf(&tmp_buf[strlen(tmp_buf)], + catgets(libmksdmsi18n_catd, 1, 110, " (ignored)")); + ); + } + (void) fprintf(stdout, "\n"); + (void) fflush(stdout); + SEND_MTOOL_MSG( + make_output_msg->appendOutput(AVO_STRDUP(tmp_buf)); + ); + } + SEND_MTOOL_MSG( + xdr_msg = (RWCollectable*) make_output_msg; + xdr(xdrs_p, xdr_msg); + delete make_output_msg; + ); + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in await(), returning failed.")); +#endif + + return failed; +} + +/* + * sh_command2string(command, destination) + * + * Run one sh command and capture the output from it. + * + * Return value: + * + * Parameters: + * command The command to run + * destination Where to deposit the output from the command + * + * Static variables used: + * + * Global variables used: + */ +void +sh_command2string(register String command, register String destination) +{ + register FILE *fd; + register int chr; + int status; + Boolean command_generated_output = false; + + command->text.p = (int) nul_char; + WCSTOMBS(mbs_buffer, command->buffer.start); + if ((fd = popen(mbs_buffer, "r")) == NULL) { + WCSTOMBS(mbs_buffer, command->buffer.start); + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 111, "Could not run command `%s' for :sh transformation"), + mbs_buffer); + } + while ((chr = getc(fd)) != EOF) { + if (chr == (int) newline_char) { + chr = (int) space_char; + } + command_generated_output = true; + append_char(chr, destination); + } + + /* + * We don't want to keep the last LINE_FEED since usually + * the output of the 'sh:' command is used to evaluate + * some MACRO. ( /bin/sh and other shell add a line feed + * to the output so that the prompt appear in the right place. + * We don't need that + */ + if (command_generated_output){ + if ( *(destination->text.p-1) == (int) space_char) { + * (-- destination->text.p) = '\0'; + } + } else { + /* + * If the command didn't generate any output, + * set the buffer to a null string. + */ + *(destination->text.p) = '\0'; + } + + status = pclose(fd); + if (status != 0) { + WCSTOMBS(mbs_buffer, command->buffer.start); + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 112, "The command `%s' returned status `%d'"), + mbs_buffer, + WEXITSTATUS(status)); + } +} + + diff --git a/usr/src/make_src/Make/lib/mksh/src/globals.cc b/usr/src/make_src/Make/lib/mksh/src/globals.cc new file mode 100644 index 0000000..2d36d24 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/globals.cc @@ -0,0 +1,140 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)globals.cc 1.16 06/12/12 + */ + +#pragma ident "@(#)globals.cc 1.16 06/12/12" + +/* + * globals.cc + * + * This declares all global variables + */ + +/* + * Included files + */ +#include <mksh/globals.h> + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Global variables + */ +char char_semantics[CHAR_SEMANTICS_ENTRIES]; +wchar_t char_semantics_char[] = { + ampersand_char, + asterisk_char, + at_char, + backquote_char, + backslash_char, + bar_char, + bracketleft_char, + bracketright_char, + colon_char, + dollar_char, + doublequote_char, + equal_char, + exclam_char, + greater_char, + hat_char, + hyphen_char, + less_char, + newline_char, + numbersign_char, + parenleft_char, + parenright_char, + percent_char, + plus_char, + question_char, + quote_char, + semicolon_char, +#ifdef SGE_SUPPORT + space_char, + tab_char, +#endif + nul_char +}; +Macro_list cond_macro_list; +Boolean conditional_macro_used; +Boolean do_not_exec_rule; /* `-n' */ +Boolean dollarget_seen; +Boolean dollarless_flag; +Name dollarless_value; +Envvar envvar; +#ifdef lint +char **environ; +#endif +#ifdef SUN5_0 +int exit_status; +#endif +wchar_t *file_being_read; +/* Variable gnu_style=true if env. var. SUN_MAKE_COMPAT_MODE=GNU (RFE 4866328) */ +Boolean gnu_style = false; +Name_set hashtab; +Name host_arch; +Name host_mach; +int line_number; +char *make_state_lockfile; +Boolean make_word_mentioned; +Makefile_type makefile_type = reading_nothing; +char mbs_buffer[(MAXPATHLEN * MB_LEN_MAX)]; +Name path_name; +Boolean posix = true; +Name hat; +Name query; +Boolean query_mentioned; +Boolean reading_environment; +Name shell_name; +Boolean svr4 = false; +Name target_arch; +Name target_mach; +Boolean tilde_rule; +Name virtual_root; +Boolean vpath_defined; +Name vpath_name; +wchar_t wcs_buffer[MAXPATHLEN]; +Boolean working_on_targets; +#if defined (TEAMWARE_MAKE_CMN) && defined(REDIRECT_ERR) +Boolean out_err_same; +#endif +pid_t childPid = -1; // This variable is used for killing child's process + // Such as qrsh, running command, etc. + +/* + * timestamps defined in defs.h + */ +const timestruc_t file_no_time = { -1, 0 }; +const timestruc_t file_doesnt_exist = { 0, 0 }; +const timestruc_t file_is_dir = { 1, 0 }; +const timestruc_t file_min_time = { 2, 0 }; +const timestruc_t file_max_time = { INT_MAX, 0 }; diff --git a/usr/src/make_src/Make/lib/mksh/src/i18n.cc b/usr/src/make_src/Make/lib/mksh/src/i18n.cc new file mode 100644 index 0000000..f12341e --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/i18n.cc @@ -0,0 +1,100 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2003 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)i18n.cc 1.3 06/12/12 + */ + +#pragma ident "@(#)i18n.cc 1.3 06/12/12" + +/* + * i18n.cc + * + * Deal with internationalization conversions + */ + +/* + * Included files + */ +#include <mksh/i18n.h> +#include <mksh/misc.h> /* setup_char_semantics() */ +#if defined (linux) +# include <wctype.h> +# include <wchar.h> +# define wschr(x,y) wcschr(x,y) +#endif + +/* + * get_char_semantics_value(ch) + * + * Return value: + * The character semantics of ch. + * + * Parameters: + * ch character we want semantics for. + * + */ +char +get_char_semantics_value(wchar_t ch) +{ + static Boolean char_semantics_setup; + + if (!char_semantics_setup) { + setup_char_semantics(); + char_semantics_setup = true; + } + return char_semantics[get_char_semantics_entry(ch)]; +} + +/* + * get_char_semantics_entry(ch) + * + * Return value: + * The slot number in the array for special make chars, + * else the slot number of the last array entry. + * + * Parameters: + * ch The wide character + * + * Global variables used: + * char_semantics_char[] array of special wchar_t chars + * "&*@`\\|[]:$=!>-\n#()%?;^<'\"" + */ +int +get_char_semantics_entry(wchar_t ch) +{ + wchar_t *char_sem_char; + + char_sem_char = (wchar_t *) wschr(char_semantics_char, ch); + if (char_sem_char == NULL) { + /* + * Return the integer entry for the last slot, + * whose content is empty. + */ + return (CHAR_SEMANTICS_ENTRIES - 1); + } else { + return (char_sem_char - char_semantics_char); + } +} + diff --git a/usr/src/make_src/Make/lib/mksh/src/libmksh.msg b/usr/src/make_src/Make/lib/mksh/src/libmksh.msg new file mode 100644 index 0000000..d1994aa --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/libmksh.msg @@ -0,0 +1,81 @@ + +$quote " + + +$set 1 +$ +$ CDDL HEADER START +$ +$ The contents of this file are subject to the terms of the +$ Common Development and Distribution License (the "License"). +$ You may not use this file except in compliance with the License. +$ +$ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +$ or http://www.opensolaris.org/os/licensing. +$ See the License for the specific language governing permissions +$ and limitations under the License. +$ +$ When distributing Covered Code, include this CDDL HEADER in each +$ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +$ If applicable, add the following below this CDDL HEADER, with the +$ fields enclosed by brackets "[]" replaced with your own identifying +$ information: Portions Copyright [yyyy] [name of copyright owner] +$ +$ CDDL HEADER END +$ +$ Copyright 1996 Sun Microsystems, Inc. All rights reserved. +$ Use is subject to license terms. +$ +$ @(#)libmksh.msg 1.2 06/12/12 +$ +89 "ulimit() failed: %s" +90 "Couldn't open standard out temp file `%s': %s" +91 "Couldn't open standard error temp file `%s': %s" +92 "Could not load `/usr/bin/nice': %s" +93 "Could not load Shell from `%s': %s" +94 "fork failed: %s" +95 "Command `%s' has more than %d arguments" +96 "Cannot load command `%s': %s" +97 "fork failed: %s" +98 "wait() failed: %s" +99 "Could not open filter file for -X" +100 "Could not stat filter file for -X" +101 "\n**** Error: Directory %s Target %s:\n%s\n" +102 "**** Error: Directory %s Target %s\n" +103 "*** Error code %d" +104 "*** Error code %d" +105 "*** Signal %d" +106 "*** Signal %d" +107 " - core dumped" +108 " - core dumped" +109 " (ignored)" +110 " (ignored)" +111 "Could not run command `%s' for :sh transformation" +112 "The command `%s' returned status `%d'" +113 "Loop detected when expanding macro value `%s'" +114 "'$' at end of string `%s'" +115 "'$' at end of line" +116 "Unmatched `%c' in string `%s'" +117 "Premature EOF" +118 "Unmatched `%c' on line" +119 "Illegal macro reference `%s'" +120 "= missing from replacement macro reference" +121 "= missing from replacement macro reference" +122 "%% missing from replacement macro reference" +123 "%% missing from replacement macro reference" +124 "Too many %% in pattern" +125 "Conditional macro `%s' referenced on line %d" +126 "Out of memory" +127 "Error %d" +128 "mksh: Fatal error: " +129 "Current working directory %s\n" +131 "mksh: Fatal error in reader: " +133 "Current working directory %s\n" +134 "mksh: Warning: " +135 "Current working directory %s\n" +136 "Internal error. Unknown prop type %d" +137 "`cd %s' failed, and conversion of %s to automounter pathname also failed" +138 "`cd %s' and `cd %s' both failed" +139 "The following command caused the error:\n%s\n" +140 "Error reading `%s': Premature EOF" +141 "Error reading `%s': %s" diff --git a/usr/src/make_src/Make/lib/mksh/src/macro.cc b/usr/src/make_src/Make/lib/mksh/src/macro.cc new file mode 100644 index 0000000..43d7603 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/macro.cc @@ -0,0 +1,1414 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)macro.cc 1.22 06/12/12 + */ + +#pragma ident "@(#)macro.cc 1.22 06/12/12" + +/* + * macro.cc + * + * Handle expansion of make macros + */ + +/* + * Included files + */ +#include <mksh/dosys.h> /* sh_command2string() */ +#include <mksh/i18n.h> /* get_char_semantics_value() */ +#include <mksh/macro.h> +#include <mksh/misc.h> /* retmem() */ +#include <mksh/read.h> /* get_next_block_fn() */ +#include <mksdmsi18n/mksdmsi18n.h> /* libmksdmsi18n_init() */ + +/* + * File table of contents + */ +static void add_macro_to_global_list(Name macro_to_add); +#ifdef NSE +static void expand_value_with_daemon(Name name, register Property macro, register String destination, Boolean cmd); +#else +static void expand_value_with_daemon(Name, register Property macro, register String destination, Boolean cmd); +#endif + +static void init_arch_macros(void); +static void init_mach_macros(void); +static Boolean init_arch_done = false; +static Boolean init_mach_done = false; + + +long env_alloc_num = 0; +long env_alloc_bytes = 0; + +/* + * getvar(name) + * + * Return expanded value of macro. + * + * Return value: + * The expanded value of the macro + * + * Parameters: + * name The name of the macro we want the value for + * + * Global variables used: + */ +Name +getvar(register Name name) +{ + String_rec destination; + wchar_t buffer[STRING_BUFFER_LENGTH]; + register Name result; + + if ((name == host_arch) || (name == target_arch)) { + if (!init_arch_done) { + init_arch_done = true; + init_arch_macros(); + } + } + if ((name == host_mach) || (name == target_mach)) { + if (!init_mach_done) { + init_mach_done = true; + init_mach_macros(); + } + } + + INIT_STRING_FROM_STACK(destination, buffer); + expand_value(maybe_append_prop(name, macro_prop)->body.macro.value, + &destination, + false); + result = GETNAME(destination.buffer.start, FIND_LENGTH); + if (destination.free_after_use) { + retmem(destination.buffer.start); + } + return result; +} + +/* + * expand_value(value, destination, cmd) + * + * Recursively expands all macros in the string value. + * destination is where the expanded value should be appended. + * + * Parameters: + * value The value we are expanding + * destination Where to deposit the expansion + * cmd If we are evaluating a command line we + * turn \ quoting off + * + * Global variables used: + */ +void +expand_value(Name value, register String destination, Boolean cmd) +{ + Source_rec sourceb; + register Source source = &sourceb; + register wchar_t *source_p = NULL; + register wchar_t *source_end = NULL; + wchar_t *block_start = NULL; + int quote_seen = 0; + + if (value == NULL) { + /* + * Make sure to get a string allocated even if it + * will be empty. + */ + MBSTOWCS(wcs_buffer, ""); + append_string(wcs_buffer, destination, FIND_LENGTH); + destination->text.end = destination->text.p; + return; + } + if (!value->dollar) { + /* + * If the value we are expanding does not contain + * any $, we don't have to parse it. + */ + APPEND_NAME(value, + destination, + (int) value->hash.length + ); + destination->text.end = destination->text.p; + return; + } + + if (value->being_expanded) { + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 113, "Loop detected when expanding macro value `%s'"), + value->string_mb); + } + value->being_expanded = true; + /* Setup the structure we read from */ + Wstring vals(value); + sourceb.string.text.p = sourceb.string.buffer.start = wsdup(vals.get_string()); + sourceb.string.free_after_use = true; + sourceb.string.text.end = + sourceb.string.buffer.end = + sourceb.string.text.p + value->hash.length; + sourceb.previous = NULL; + sourceb.fd = -1; + sourceb.inp_buf = + sourceb.inp_buf_ptr = + sourceb.inp_buf_end = NULL; + sourceb.error_converting = false; + /* Lift some pointers from the struct to local register variables */ + CACHE_SOURCE(0); +/* We parse the string in segments */ +/* We read chars until we find a $, then we append what we have read so far */ +/* (since last $ processing) to the destination. When we find a $ we call */ +/* expand_macro() and let it expand that particular $ reference into dest */ + block_start = source_p; + quote_seen = 0; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case backslash_char: + /* Quote $ in macro value */ + if (!cmd) { + quote_seen = ~quote_seen; + } + continue; + case dollar_char: + /* Save the plain string we found since */ + /* start of string or previous $ */ + if (quote_seen) { + append_string(block_start, + destination, + source_p - block_start - 1); + block_start = source_p; + break; + } + append_string(block_start, + destination, + source_p - block_start); + source->string.text.p = ++source_p; + UNCACHE_SOURCE(); + /* Go expand the macro reference */ + expand_macro(source, destination, sourceb.string.buffer.start, cmd); + CACHE_SOURCE(1); + block_start = source_p + 1; + break; + case nul_char: + /* The string ran out. Get some more */ + append_string(block_start, + destination, + source_p - block_start); + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + destination->text.end = destination->text.p; + value->being_expanded = false; + return; + } + if (source->error_converting) { + fatal_reader_mksh(NOCATGETS("Internal error: Invalid byte sequence in expand_value()")); + } + block_start = source_p; + source_p--; + continue; + } + quote_seen = 0; + } + retmem(sourceb.string.buffer.start); +} + +/* + * expand_macro(source, destination, current_string, cmd) + * + * Should be called with source->string.text.p pointing to + * the first char after the $ that starts a macro reference. + * source->string.text.p is returned pointing to the first char after + * the macro name. + * It will read the macro name, expanding any macros in it, + * and get the value. The value is then expanded. + * destination is a String that is filled in with the expanded macro. + * It may be passed in referencing a buffer to expand the macro into. + * Note that most expansions are done on demand, e.g. right + * before the command is executed and not while the file is + * being parsed. + * + * Parameters: + * source The source block that references the string + * to expand + * destination Where to put the result + * current_string The string we are expanding, for error msg + * cmd If we are evaluating a command line we + * turn \ quoting off + * + * Global variables used: + * funny Vector of semantic tags for characters + * is_conditional Set if a conditional macro is refd + * make_word_mentioned Set if the word "MAKE" is mentioned + * makefile_type We deliver extra msg when reading makefiles + * query The Name "?", compared against + * query_mentioned Set if the word "?" is mentioned + */ +void +expand_macro(register Source source, register String destination, wchar_t *current_string, Boolean cmd) +{ + static Name make = (Name)NULL; + static wchar_t colon_sh[4]; + static wchar_t colon_shell[7]; + String_rec string; + wchar_t buffer[STRING_BUFFER_LENGTH]; + register wchar_t *source_p = source->string.text.p; + register wchar_t *source_end = source->string.text.end; + register int closer = 0; + wchar_t *block_start = (wchar_t *)NULL; + int quote_seen = 0; + register int closer_level = 1; + Name name = (Name)NULL; + wchar_t *colon = (wchar_t *)NULL; + wchar_t *percent = (wchar_t *)NULL; + wchar_t *eq = (wchar_t *) NULL; + Property macro = NULL; + wchar_t *p = (wchar_t*)NULL; + String_rec extracted; + wchar_t extracted_string[MAXPATHLEN]; + wchar_t *left_head = NULL; + wchar_t *left_tail = NULL; + wchar_t *right_tail = NULL; + int left_head_len = 0; + int left_tail_len = 0; + int tmp_len = 0; + wchar_t *right_hand[128]; + int i = 0; + enum { + no_extract, + dir_extract, + file_extract + } extraction = no_extract; + enum { + no_replace, + suffix_replace, + pattern_replace, + sh_replace + } replacement = no_replace; + + if (make == NULL) { + MBSTOWCS(wcs_buffer, NOCATGETS("MAKE")); + make = GETNAME(wcs_buffer, FIND_LENGTH); + + MBSTOWCS(colon_sh, NOCATGETS(":sh")); + MBSTOWCS(colon_shell, NOCATGETS(":shell")); + } + + right_hand[0] = NULL; + + /* First copy the (macro-expanded) macro name into string. */ + INIT_STRING_FROM_STACK(string, buffer); +recheck_first_char: + /* Check the first char of the macro name to figure out what to do. */ + switch (GET_CHAR()) { + case nul_char: + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + WCSTOMBS(mbs_buffer, current_string); + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 114, "'$' at end of string `%s'"), + mbs_buffer); + } + if (source->error_converting) { + fatal_reader_mksh(NOCATGETS("Internal error: Invalid byte sequence in expand_macro()")); + } + goto recheck_first_char; + case parenleft_char: + /* Multi char name. */ + closer = (int) parenright_char; + break; + case braceleft_char: + /* Multi char name. */ + closer = (int) braceright_char; + break; + case newline_char: + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 115, "'$' at end of line")); + default: + /* Single char macro name. Just suck it up */ + append_char(*source_p, &string); + source->string.text.p = source_p + 1; + goto get_macro_value; + } + + /* Handle multi-char macro names */ + block_start = ++source_p; + quote_seen = 0; + for (; 1; source_p++) { + switch (GET_CHAR()) { + case nul_char: + append_string(block_start, + &string, + source_p - block_start); + GET_NEXT_BLOCK_NOCHK(source); + if (source == NULL) { + if (current_string != NULL) { + WCSTOMBS(mbs_buffer, current_string); + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 116, "Unmatched `%c' in string `%s'"), + closer == + (int) braceright_char ? + (int) braceleft_char : + (int) parenleft_char, + mbs_buffer); + } else { + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 117, "Premature EOF")); + } + } + if (source->error_converting) { + fatal_reader_mksh(NOCATGETS("Internal error: Invalid byte sequence in expand_macro()")); + } + block_start = source_p; + source_p--; + continue; + case newline_char: + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 118, "Unmatched `%c' on line"), + closer == (int) braceright_char ? + (int) braceleft_char : + (int) parenleft_char); + case backslash_char: + /* Quote dollar in macro value. */ + if (!cmd) { + quote_seen = ~quote_seen; + } + continue; + case dollar_char: + /* + * Macro names may reference macros. + * This expands the value of such macros into the + * macro name string. + */ + if (quote_seen) { + append_string(block_start, + &string, + source_p - block_start - 1); + block_start = source_p; + break; + } + append_string(block_start, + &string, + source_p - block_start); + source->string.text.p = ++source_p; + UNCACHE_SOURCE(); + expand_macro(source, &string, current_string, cmd); + CACHE_SOURCE(0); + block_start = source_p; + source_p--; + break; + case parenleft_char: + /* Allow nested pairs of () in the macro name. */ + if (closer == (int) parenright_char) { + closer_level++; + } + break; + case braceleft_char: + /* Allow nested pairs of {} in the macro name. */ + if (closer == (int) braceright_char) { + closer_level++; + } + break; + case parenright_char: + case braceright_char: + /* + * End of the name. Save the string in the macro + * name string. + */ + if ((*source_p == closer) && (--closer_level <= 0)) { + source->string.text.p = source_p + 1; + append_string(block_start, + &string, + source_p - block_start); + goto get_macro_value; + } + break; + } + quote_seen = 0; + } + /* + * We got the macro name. We now inspect it to see if it + * specifies any translations of the value. + */ +get_macro_value: + name = NULL; + /* First check if we have a $(@D) type translation. */ + if ((get_char_semantics_value(string.buffer.start[0]) & + (int) special_macro_sem) && + (string.text.p - string.buffer.start >= 2) && + ((string.buffer.start[1] == 'D') || + (string.buffer.start[1] == 'F'))) { + switch (string.buffer.start[1]) { + case 'D': + extraction = dir_extract; + break; + case 'F': + extraction = file_extract; + break; + default: + WCSTOMBS(mbs_buffer, string.buffer.start); + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 119, "Illegal macro reference `%s'"), + mbs_buffer); + } + /* Internalize the macro name using the first char only. */ + name = GETNAME(string.buffer.start, 1); + (void) wscpy(string.buffer.start, string.buffer.start + 2); + } + /* Check for other kinds of translations. */ + if ((colon = (wchar_t *) wschr(string.buffer.start, + (int) colon_char)) != NULL) { + /* + * We have a $(FOO:.c=.o) type translation. + * Get the name of the macro proper. + */ + if (name == NULL) { + name = GETNAME(string.buffer.start, + colon - string.buffer.start); + } + /* Pickup all the translations. */ + if (IS_WEQUAL(colon, colon_sh) || IS_WEQUAL(colon, colon_shell)) { + replacement = sh_replace; + } else if ((svr4) || + ((percent = (wchar_t *) wschr(colon + 1, + (int) percent_char)) == NULL)) { + while (colon != NULL) { + if ((eq = (wchar_t *) wschr(colon + 1, + (int) equal_char)) == NULL) { + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 120, "= missing from replacement macro reference")); + } + left_tail_len = eq - colon - 1; + if(left_tail) { + retmem(left_tail); + } + left_tail = ALLOC_WC(left_tail_len + 1); + (void) wsncpy(left_tail, + colon + 1, + eq - colon - 1); + left_tail[eq - colon - 1] = (int) nul_char; + replacement = suffix_replace; + if ((colon = (wchar_t *) wschr(eq + 1, + (int) colon_char)) != NULL) { + tmp_len = colon - eq; + if(right_tail) { + retmem(right_tail); + } + right_tail = ALLOC_WC(tmp_len); + (void) wsncpy(right_tail, + eq + 1, + colon - eq - 1); + right_tail[colon - eq - 1] = + (int) nul_char; + } else { + if(right_tail) { + retmem(right_tail); + } + right_tail = ALLOC_WC(wslen(eq) + 1); + (void) wscpy(right_tail, eq + 1); + } + } + } else { + if ((eq = (wchar_t *) wschr(colon + 1, + (int) equal_char)) == NULL) { + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 121, "= missing from replacement macro reference")); + } + if ((percent = (wchar_t *) wschr(colon + 1, + (int) percent_char)) == NULL) { + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 122, "%% missing from replacement macro reference")); + } + if (eq < percent) { + fatal_reader_mksh(catgets(libmksdmsi18n_catd, 1, 123, "%% missing from replacement macro reference")); + } + + if (percent > (colon + 1)) { + tmp_len = percent - colon; + if(left_head) { + retmem(left_head); + } + left_head = ALLOC_WC(tmp_len); + (void) wsncpy(left_head, + colon + 1, + percent - colon - 1); + left_head[percent-colon-1] = (int) nul_char; + left_head_len = percent-colon-1; + } else { + left_head = NULL; + left_head_len = 0; + } + + if (eq > percent+1) { + tmp_len = eq - percent; + if(left_tail) { + retmem(left_tail); + } + left_tail = ALLOC_WC(tmp_len); + (void) wsncpy(left_tail, + percent + 1, + eq - percent - 1); + left_tail[eq-percent-1] = (int) nul_char; + left_tail_len = eq-percent-1; + } else { + left_tail = NULL; + left_tail_len = 0; + } + + if ((percent = (wchar_t *) wschr(++eq, + (int) percent_char)) == NULL) { + + right_hand[0] = ALLOC_WC(wslen(eq) + 1); + right_hand[1] = NULL; + (void) wscpy(right_hand[0], eq); + } else { + i = 0; + do { + right_hand[i] = ALLOC_WC(percent-eq+1); + (void) wsncpy(right_hand[i], + eq, + percent - eq); + right_hand[i][percent-eq] = + (int) nul_char; + if (i++ >= VSIZEOF(right_hand)) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 124, "Too many %% in pattern")); + } + eq = percent + 1; + if (eq[0] == (int) nul_char) { + MBSTOWCS(wcs_buffer, ""); + right_hand[i] = (wchar_t *) wsdup(wcs_buffer); + i++; + break; + } + } while ((percent = (wchar_t *) wschr(eq, (int) percent_char)) != NULL); + if (eq[0] != (int) nul_char) { + right_hand[i] = ALLOC_WC(wslen(eq) + 1); + (void) wscpy(right_hand[i], eq); + i++; + } + right_hand[i] = NULL; + } + replacement = pattern_replace; + } + } + if (name == NULL) { + /* + * No translations found. + * Use the whole string as the macro name. + */ + name = GETNAME(string.buffer.start, + string.text.p - string.buffer.start); + } + if (string.free_after_use) { + retmem(string.buffer.start); + } + if (name == make) { + make_word_mentioned = true; + } + if (name == query) { + query_mentioned = true; + } + if ((name == host_arch) || (name == target_arch)) { + if (!init_arch_done) { + init_arch_done = true; + init_arch_macros(); + } + } + if ((name == host_mach) || (name == target_mach)) { + if (!init_mach_done) { + init_mach_done = true; + init_mach_macros(); + } + } + /* Get the macro value. */ + macro = get_prop(name->prop, macro_prop); +#ifdef NSE + if (nse_watch_vars && nse && macro != NULL) { + if (macro->body.macro.imported) { + nse_shell_var_used= name; + } + if (macro->body.macro.value != NULL){ + if (nse_backquotes(macro->body.macro.value->string)) { + nse_backquote_seen= name; + } + } + } +#endif + if ((macro != NULL) && macro->body.macro.is_conditional) { + conditional_macro_used = true; + /* + * Add this conditional macro to the beginning of the + * global list. + */ + add_macro_to_global_list(name); + if (makefile_type == reading_makefile) { + warning_mksh(catgets(libmksdmsi18n_catd, 1, 164, "Conditional macro `%s' referenced in file `%ws', line %d"), + name->string_mb, file_being_read, line_number); + } + } + /* Macro name read and parsed. Expand the value. */ + if ((macro == NULL) || (macro->body.macro.value == NULL)) { + /* If the value is empty, we just get out of here. */ + goto exit; + } + if (replacement == sh_replace) { + /* If we should do a :sh transform, we expand the command + * and process it. + */ + INIT_STRING_FROM_STACK(string, buffer); + /* Expand the value into a local string buffer and run cmd. */ + expand_value_with_daemon(name, macro, &string, cmd); + sh_command2string(&string, destination); + } else if ((replacement != no_replace) || (extraction != no_extract)) { + /* + * If there were any transforms specified in the macro + * name, we deal with them here. + */ + INIT_STRING_FROM_STACK(string, buffer); + /* Expand the value into a local string buffer. */ + expand_value_with_daemon(name, macro, &string, cmd); + /* Scan the expanded string. */ + p = string.buffer.start; + while (*p != (int) nul_char) { + wchar_t chr; + + /* + * First skip over any white space and append + * that to the destination string. + */ + block_start = p; + while ((*p != (int) nul_char) && iswspace(*p)) { + p++; + } + append_string(block_start, + destination, + p - block_start); + /* Then find the end of the next word. */ + block_start = p; + while ((*p != (int) nul_char) && !iswspace(*p)) { + p++; + } + /* If we cant find another word we are done */ + if (block_start == p) { + break; + } + /* Then apply the transforms to the word */ + INIT_STRING_FROM_STACK(extracted, extracted_string); + switch (extraction) { + case dir_extract: + /* + * $(@D) type transform. Extract the + * path from the word. Deliver "." if + * none is found. + */ + if (p != NULL) { + chr = *p; + *p = (int) nul_char; + } + eq = (wchar_t *) wsrchr(block_start, (int) slash_char); + if (p != NULL) { + *p = chr; + } + if ((eq == NULL) || (eq > p)) { + MBSTOWCS(wcs_buffer, "."); + append_string(wcs_buffer, &extracted, 1); + } else { + append_string(block_start, + &extracted, + eq - block_start); + } + break; + case file_extract: + /* + * $(@F) type transform. Remove the path + * from the word if any. + */ + if (p != NULL) { + chr = *p; + *p = (int) nul_char; + } + eq = (wchar_t *) wsrchr(block_start, (int) slash_char); + if (p != NULL) { + *p = chr; + } + if ((eq == NULL) || (eq > p)) { + append_string(block_start, + &extracted, + p - block_start); + } else { + append_string(eq + 1, + &extracted, + p - eq - 1); + } + break; + case no_extract: + append_string(block_start, + &extracted, + p - block_start); + break; + } + switch (replacement) { + case suffix_replace: + /* + * $(FOO:.o=.c) type transform. + * Maybe replace the tail of the word. + */ + if (((extracted.text.p - + extracted.buffer.start) >= + left_tail_len) && + IS_WEQUALN(extracted.text.p - left_tail_len, + left_tail, + left_tail_len)) { + append_string(extracted.buffer.start, + destination, + (extracted.text.p - + extracted.buffer.start) + - left_tail_len); + append_string(right_tail, + destination, + FIND_LENGTH); + } else { + append_string(extracted.buffer.start, + destination, + FIND_LENGTH); + } + break; + case pattern_replace: + /* $(X:a%b=c%d) type transform. */ + if (((extracted.text.p - + extracted.buffer.start) >= + left_head_len+left_tail_len) && + IS_WEQUALN(left_head, + extracted.buffer.start, + left_head_len) && + IS_WEQUALN(left_tail, + extracted.text.p - left_tail_len, + left_tail_len)) { + i = 0; + while (right_hand[i] != NULL) { + append_string(right_hand[i], + destination, + FIND_LENGTH); + i++; + if (right_hand[i] != NULL) { + append_string(extracted.buffer. + start + + left_head_len, + destination, + (extracted.text.p - extracted.buffer.start)-left_head_len-left_tail_len); + } + } + } else { + append_string(extracted.buffer.start, + destination, + FIND_LENGTH); + } + break; + case no_replace: + append_string(extracted.buffer.start, + destination, + FIND_LENGTH); + break; + case sh_replace: + break; + } + } + if (string.free_after_use) { + retmem(string.buffer.start); + } + } else { + /* + * This is for the case when the macro name did not + * specify transforms. + */ + if (!strncmp(name->string_mb, NOCATGETS("GET"), 3)) { + dollarget_seen = true; + } + dollarless_flag = false; + if (!strncmp(name->string_mb, "<", 1) && + dollarget_seen) { + dollarless_flag = true; + dollarget_seen = false; + } + expand_value_with_daemon(name, macro, destination, cmd); + } +exit: + if(left_tail) { + retmem(left_tail); + } + if(right_tail) { + retmem(right_tail); + } + if(left_head) { + retmem(left_head); + } + i = 0; + while (right_hand[i] != NULL) { + retmem(right_hand[i]); + i++; + } + *destination->text.p = (int) nul_char; + destination->text.end = destination->text.p; +} + +static void +add_macro_to_global_list(Name macro_to_add) +{ + Macro_list new_macro; + Macro_list macro_on_list; + char *name_on_list = (char*)NULL; + char *name_to_add = macro_to_add->string_mb; + char *value_on_list = (char*)NULL; + char *value_to_add = (char*)NULL; + + if (macro_to_add->prop->body.macro.value != NULL) { + value_to_add = macro_to_add->prop->body.macro.value->string_mb; + } else { + value_to_add = ""; + } + + /* + * Check if this macro is already on list, if so, do nothing + */ + for (macro_on_list = cond_macro_list; + macro_on_list != NULL; + macro_on_list = macro_on_list->next) { + + name_on_list = macro_on_list->macro_name; + value_on_list = macro_on_list->value; + + if (IS_EQUAL(name_on_list, name_to_add)) { + if (IS_EQUAL(value_on_list, value_to_add)) { + return; + } + } + } + new_macro = (Macro_list) malloc(sizeof(Macro_list_rec)); + new_macro->macro_name = strdup(name_to_add); + new_macro->value = strdup(value_to_add); + new_macro->next = cond_macro_list; + cond_macro_list = new_macro; +} + +/* + * init_arch_macros(void) + * + * Set the magic macros TARGET_ARCH, HOST_ARCH, + * + * Parameters: + * + * Global variables used: + * host_arch Property for magic macro HOST_ARCH + * target_arch Property for magic macro TARGET_ARCH + * + * Return value: + * The function does not return a value, but can + * call fatal() in case of error. + */ +static void +init_arch_macros(void) +{ + String_rec result_string; + wchar_t wc_buf[STRING_BUFFER_LENGTH]; + char mb_buf[STRING_BUFFER_LENGTH]; + FILE *pipe; + Name value; + int set_host, set_target; +#ifdef NSE + Property macro; +#endif +#if defined(linux) + const char *mach_command = NOCATGETS("/bin/uname -p"); +#else + const char *mach_command = NOCATGETS("/bin/mach"); +#endif + + set_host = (get_prop(host_arch->prop, macro_prop) == NULL); + set_target = (get_prop(target_arch->prop, macro_prop) == NULL); + + if (set_host || set_target) { + INIT_STRING_FROM_STACK(result_string, wc_buf); + append_char((int) hyphen_char, &result_string); + + if ((pipe = popen(mach_command, "r")) == NULL) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 185, "Execute of %s failed"), mach_command); + } + while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) { + MBSTOWCS(wcs_buffer, mb_buf); + append_string(wcs_buffer, &result_string, wslen(wcs_buffer)); + } + if (pclose(pipe) != 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 186, "Execute of %s failed"), mach_command); + } + + value = GETNAME(result_string.buffer.start, wslen(result_string.buffer.start)); + +#ifdef NSE + macro = setvar_daemon(host_arch, value, false, no_daemon, true, 0); + macro->body.macro.imported= true; + macro = setvar_daemon(target_arch, value, false, no_daemon, true, 0); + macro->body.macro.imported= true; +#else + if (set_host) { + (void) setvar_daemon(host_arch, value, false, no_daemon, true, 0); + } + if (set_target) { + (void) setvar_daemon(target_arch, value, false, no_daemon, true, 0); + } +#endif + } +} + +/* + * init_mach_macros(void) + * + * Set the magic macros TARGET_MACH, HOST_MACH, + * + * Parameters: + * + * Global variables used: + * host_mach Property for magic macro HOST_MACH + * target_mach Property for magic macro TARGET_MACH + * + * Return value: + * The function does not return a value, but can + * call fatal() in case of error. + */ +static void +init_mach_macros(void) +{ + String_rec result_string; + wchar_t wc_buf[STRING_BUFFER_LENGTH]; + char mb_buf[STRING_BUFFER_LENGTH]; + FILE *pipe; + Name value; + int set_host, set_target; + const char *arch_command = NOCATGETS("/bin/arch"); + + set_host = (get_prop(host_mach->prop, macro_prop) == NULL); + set_target = (get_prop(target_mach->prop, macro_prop) == NULL); + + if (set_host || set_target) { + INIT_STRING_FROM_STACK(result_string, wc_buf); + append_char((int) hyphen_char, &result_string); + + if ((pipe = popen(arch_command, "r")) == NULL) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 183, "Execute of %s failed"), arch_command); + } + while (fgets(mb_buf, sizeof(mb_buf), pipe) != NULL) { + MBSTOWCS(wcs_buffer, mb_buf); + append_string(wcs_buffer, &result_string, wslen(wcs_buffer)); + } + if (pclose(pipe) != 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 184, "Execute of %s failed"), arch_command); + } + + value = GETNAME(result_string.buffer.start, wslen(result_string.buffer.start)); + + if (set_host) { + (void) setvar_daemon(host_mach, value, false, no_daemon, true, 0); + } + if (set_target) { + (void) setvar_daemon(target_mach, value, false, no_daemon, true, 0); + } + } +} + +/* + * expand_value_with_daemon(name, macro, destination, cmd) + * + * Checks for daemons and then maybe calls expand_value(). + * + * Parameters: + * name Name of the macro (Added by the NSE) + * macro The property block with the value to expand + * destination Where the result should be deposited + * cmd If we are evaluating a command line we + * turn \ quoting off + * + * Global variables used: + */ +static void +#ifdef NSE +expand_value_with_daemon(Name name, register Property macro, register String destination, Boolean cmd) +#else +expand_value_with_daemon(Name, register Property macro, register String destination, Boolean cmd) +#endif +{ + register Chain chain; + +#ifdef NSE + if (reading_dependencies) { + /* + * Processing the dependencies themselves + */ + depvar_dep_macro_used(name); + } else { + /* + * Processing the rules for the targets + * the nse_watch_vars flags chokes off most + * checks. it is true only when processing + * the output from a recursive make run + * which is all we are interested in here. + */ + if (nse_watch_vars) { + depvar_rule_macro_used(name); + } + } +#endif + + switch (macro->body.macro.daemon) { + case no_daemon: + if (!svr4 && !posix) { + expand_value(macro->body.macro.value, destination, cmd); + } else { + if (dollarless_flag && tilde_rule) { + expand_value(dollarless_value, destination, cmd); + dollarless_flag = false; + tilde_rule = false; + } else { + expand_value(macro->body.macro.value, destination, cmd); + } + } + return; + case chain_daemon: + /* If this is a $? value we call the daemon to translate the */ + /* list of names to a string */ + for (chain = (Chain) macro->body.macro.value; + chain != NULL; + chain = chain->next) { + APPEND_NAME(chain->name, + destination, + (int) chain->name->hash.length); + if (chain->next != NULL) { + append_char((int) space_char, destination); + } + } + return; + } +} + +/* + * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value. + */ +char *sunpro_dependencies_buf = NULL; +char *sunpro_dependencies_oldbuf = NULL; +int sunpro_dependencies_buf_size = 0; + +/* + * setvar_daemon(name, value, append, daemon, strip_trailing_spaces) + * + * Set a macro value, possibly supplying a daemon to be used + * when referencing the value. + * + * Return value: + * The property block with the new value + * + * Parameters: + * name Name of the macro to set + * value The value to set + * append Should we reset or append to the current value? + * daemon Special treatment when reading the value + * strip_trailing_spaces from the end of value->string + * debug_level Indicates how much tracing we should do + * + * Global variables used: + * makefile_type Used to check if we should enforce read only + * path_name The Name "PATH", compared against + * virtual_root The Name "VIRTUAL_ROOT", compared against + * vpath_defined Set if the macro VPATH is set + * vpath_name The Name "VPATH", compared against + * envvar A list of environment vars with $ in value + */ +Property +setvar_daemon(register Name name, register Name value, Boolean append, Daemon daemon, Boolean strip_trailing_spaces, short debug_level) +{ + register Property macro = maybe_append_prop(name, macro_prop); + register Property macro_apx = get_prop(name->prop, macro_append_prop); + int length = 0; + String_rec destination; + wchar_t buffer[STRING_BUFFER_LENGTH]; + register Chain chain; + Name val; + wchar_t *val_string = (wchar_t*)NULL; + Wstring wcb; + +#ifdef NSE + macro->body.macro.imported = false; +#endif + + if ((makefile_type != reading_nothing) && + macro->body.macro.read_only) { + return macro; + } + /* Strip spaces from the end of the value */ + if (daemon == no_daemon) { + if(value != NULL) { + wcb.init(value); + length = wcb.length(); + val_string = wcb.get_string(); + } + if ((length > 0) && iswspace(val_string[length-1])) { + INIT_STRING_FROM_STACK(destination, buffer); + buffer[0] = 0; + append_string(val_string, &destination, length); + if (strip_trailing_spaces) { + while ((length > 0) && + iswspace(destination.buffer.start[length-1])) { + destination.buffer.start[--length] = 0; + } + } + value = GETNAME(destination.buffer.start, FIND_LENGTH); + } + } + + if(macro_apx != NULL) { + val = macro_apx->body.macro_appendix.value; + } else { + val = macro->body.macro.value; + } + + if (append) { + /* + * If we are appending, we just tack the new value after + * the old one with a space in between. + */ + INIT_STRING_FROM_STACK(destination, buffer); + buffer[0] = 0; + if ((macro != NULL) && (val != NULL)) { + APPEND_NAME(val, + &destination, + (int) val->hash.length); + if (value != NULL) { + wcb.init(value); + if(wcb.length() > 0) { + MBTOWC(wcs_buffer, " "); + append_char(wcs_buffer[0], &destination); + } + } + } + if (value != NULL) { + APPEND_NAME(value, + &destination, + (int) value->hash.length); + } + value = GETNAME(destination.buffer.start, FIND_LENGTH); + wcb.init(value); + if (destination.free_after_use) { + retmem(destination.buffer.start); + } + } + + /* Debugging trace */ + if (debug_level > 1) { + if (value != NULL) { + switch (daemon) { + case chain_daemon: + (void) printf("%s =", name->string_mb); + for (chain = (Chain) value; + chain != NULL; + chain = chain->next) { + (void) printf(" %s", chain->name->string_mb); + } + (void) printf("\n"); + break; + case no_daemon: + (void) printf("%s= %s\n", + name->string_mb, + value->string_mb); + break; + } + } else { + (void) printf("%s =\n", name->string_mb); + } + } + /* Set the new values in the macro property block */ +/**/ + if(macro_apx != NULL) { + macro_apx->body.macro_appendix.value = value; + INIT_STRING_FROM_STACK(destination, buffer); + buffer[0] = 0; + if (value != NULL) { + APPEND_NAME(value, + &destination, + (int) value->hash.length); + if (macro_apx->body.macro_appendix.value_to_append != NULL) { + MBTOWC(wcs_buffer, " "); + append_char(wcs_buffer[0], &destination); + } + } + if (macro_apx->body.macro_appendix.value_to_append != NULL) { + APPEND_NAME(macro_apx->body.macro_appendix.value_to_append, + &destination, + (int) macro_apx->body.macro_appendix.value_to_append->hash.length); + } + value = GETNAME(destination.buffer.start, FIND_LENGTH); + if (destination.free_after_use) { + retmem(destination.buffer.start); + } + } +/**/ + macro->body.macro.value = value; + macro->body.macro.daemon = daemon; + /* + * If the user changes the VIRTUAL_ROOT, we need to flush + * the vroot package cache. + */ + if (name == path_name) { + flush_path_cache(); + } + if (name == virtual_root) { + flush_vroot_cache(); + } + /* If this sets the VPATH we remember that */ + if ((name == vpath_name) && + (value != NULL) && + (value->hash.length > 0)) { + vpath_defined = true; + } + /* + * For environment variables we also set the + * environment value each time. + */ + if (macro->body.macro.exported) { + static char *env; + +#ifdef DISTRIBUTED + if (!reading_environment && (value != NULL)) { +#else + if (!reading_environment && (value != NULL) && value->dollar) { +#endif + Envvar p; + + for (p = envvar; p != NULL; p = p->next) { + if (p->name == name) { + p->value = value; + p->already_put = false; + goto found_it; + } + } + p = ALLOC(Envvar); + p->name = name; + p->value = value; + p->next = envvar; + p->env_string = NULL; + p->already_put = false; + envvar = p; +found_it:; +#ifdef DISTRIBUTED + } + if (reading_environment || (value == NULL) || !value->dollar) { +#else + } else { +#endif + length = 2 + strlen(name->string_mb); + if (value != NULL) { + length += strlen(value->string_mb); + } + Property env_prop = maybe_append_prop(name, env_mem_prop); + /* + * We use a permanent buffer to reset SUNPRO_DEPENDENCIES value. + */ + if (!strncmp(name->string_mb, NOCATGETS("SUNPRO_DEPENDENCIES"), 19)) { + if (length >= sunpro_dependencies_buf_size) { + sunpro_dependencies_buf_size=length*2; + if (sunpro_dependencies_buf_size < 4096) + sunpro_dependencies_buf_size = 4096; // Default minimum size + if (sunpro_dependencies_buf) + sunpro_dependencies_oldbuf = sunpro_dependencies_buf; + sunpro_dependencies_buf=getmem(sunpro_dependencies_buf_size); + } + env = sunpro_dependencies_buf; + } else { + env = getmem(length); + } + env_alloc_num++; + env_alloc_bytes += length; + (void) sprintf(env, + "%s=%s", + name->string_mb, + value == NULL ? + "" : value->string_mb); + (void) putenv(env); + env_prop->body.env_mem.value = env; + if (sunpro_dependencies_oldbuf) { + /* Return old buffer */ + retmem_mb(sunpro_dependencies_oldbuf); + sunpro_dependencies_oldbuf = NULL; + } + } + } + if (name == target_arch) { + Name ha = getvar(host_arch); + Name ta = getvar(target_arch); + Name vr = getvar(virtual_root); + int length; + wchar_t *new_value; + wchar_t *old_vr; + Boolean new_value_allocated = false; + + Wstring ha_str(ha); + Wstring ta_str(ta); + Wstring vr_str(vr); + + wchar_t * wcb_ha = ha_str.get_string(); + wchar_t * wcb_ta = ta_str.get_string(); + wchar_t * wcb_vr = vr_str.get_string(); + + length = 32 + + wslen(wcb_ha) + + wslen(wcb_ta) + + wslen(wcb_vr); + old_vr = wcb_vr; + MBSTOWCS(wcs_buffer, NOCATGETS("/usr/arch/")); + if (IS_WEQUALN(old_vr, + wcs_buffer, + wslen(wcs_buffer))) { + old_vr = (wchar_t *) wschr(old_vr, (int) colon_char) + 1; + } + if ( (ha == ta) || (wslen(wcb_ta) == 0) ) { + new_value = old_vr; + } else { + new_value = ALLOC_WC(length); + new_value_allocated = true; + WCSTOMBS(mbs_buffer, old_vr); +#if !defined(linux) + (void) wsprintf(new_value, + NOCATGETS("/usr/arch/%s/%s:%s"), + ha->string_mb + 1, + ta->string_mb + 1, + mbs_buffer); +#else + char * mbs_new_value = (char *)getmem(length); + (void) sprintf(mbs_new_value, + NOCATGETS("/usr/arch/%s/%s:%s"), + ha->string_mb + 1, + ta->string_mb + 1, + mbs_buffer); + MBSTOWCS(new_value, mbs_new_value); + retmem_mb(mbs_new_value); +#endif + } + if (new_value[0] != 0) { + (void) setvar_daemon(virtual_root, + GETNAME(new_value, FIND_LENGTH), + false, + no_daemon, + true, + debug_level); + } + if (new_value_allocated) { + retmem(new_value); + } + } + return macro; +} diff --git a/usr/src/make_src/Make/lib/mksh/src/misc.cc b/usr/src/make_src/Make/lib/mksh/src/misc.cc new file mode 100644 index 0000000..17a878b --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/misc.cc @@ -0,0 +1,1178 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)misc.cc 1.31 06/12/12 + */ + +#pragma ident "@(#)misc.cc 1.31 06/12/12" + +/* + * misc.cc + * + * This file contains various unclassified routines. Some main groups: + * getname + * Memory allocation + * String handling + * Property handling + * Error message handling + * Make internal state dumping + * main routine support + */ + +/* + * Included files + */ +#include <bsd/bsd.h> /* bsd_signal() */ +#include <mksh/i18n.h> /* get_char_semantics_value() */ +#include <mksh/misc.h> +#include <mksdmsi18n/mksdmsi18n.h> +#include <stdarg.h> /* va_list, va_start(), va_end() */ +#include <stdlib.h> /* mbstowcs() */ +#include <sys/signal.h> /* SIG_DFL */ +#include <sys/wait.h> /* wait() */ + +#ifdef SUN5_0 +#include <string.h> /* strerror() */ +#endif + +#if defined (HP_UX) || defined (linux) +#include <unistd.h> +#endif + +/* + * Defined macros + */ + +/* + * typedefs & structs + */ + +/* + * Static variables + */ +#ifdef SUN5_0 +extern "C" void (*sigivalue)(int) = SIG_DFL; +extern "C" void (*sigqvalue)(int) = SIG_DFL; +extern "C" void (*sigtvalue)(int) = SIG_DFL; +extern "C" void (*sighvalue)(int) = SIG_DFL; +#else +static void (*sigivalue)(int) = (void (*) (int)) SIG_DFL; +static void (*sigqvalue)(int) = (void (*) (int)) SIG_DFL; +static void (*sigtvalue)(int) = (void (*) (int)) SIG_DFL; +static void (*sighvalue)(int) = (void (*) (int)) SIG_DFL; +#endif + +long getname_bytes_count = 0; +long getname_names_count = 0; +long getname_struct_count = 0; + +long freename_bytes_count = 0; +long freename_names_count = 0; +long freename_struct_count = 0; + +long expandstring_count = 0; +long getwstring_count = 0; + +/* + * File table of contents + */ +static void expand_string(register String string, register int length); + +#define FATAL_ERROR_MSG_SIZE 200 + +/* + * getmem(size) + * + * malloc() version that checks the returned value. + * + * Return value: + * The memory chunk we allocated + * + * Parameters: + * size The size of the chunk we need + * + * Global variables used: + */ +char * +getmem(register int size) +{ + register char *result = (char *) malloc((unsigned) size); + if (result == NULL) { + char buf[FATAL_ERROR_MSG_SIZE]; + sprintf(buf, NOCATGETS("*** Error: malloc(%d) failed: %s\n"), size, strerror(errno)); + strcat(buf, catgets(libmksdmsi18n_catd, 1, 126, "mksh: Fatal error: Out of memory\n")); + fputs(buf, stderr); +#ifdef SUN5_0 + exit_status = 1; +#endif + exit(1); + } + return result; +} + +/* + * retmem(p) + * + * Cover funtion for free() to make it possible to insert advises. + * + * Parameters: + * p The memory block to free + * + * Global variables used: + */ +void +retmem(wchar_t *p) +{ + (void) free((char *) p); +} + +void +retmem_mb(caddr_t p) +{ + (void) free(p); +} + +/* + * getname_fn(name, len, dont_enter) + * + * Hash a name string to the corresponding nameblock. + * + * Return value: + * The Name block for the string + * + * Parameters: + * name The string we want to internalize + * len The length of that string + * dont_enter Don't enter the name if it does not exist + * + * Global variables used: + * funny The vector of semantic tags for characters + * hashtab The hashtable used for the nametable + */ +Name +getname_fn(wchar_t *name, register int len, register Boolean dont_enter, register Boolean * foundp) +{ + register int length; + register wchar_t *cap = name; + register Name np; + static Name_rec empty_Name; + char *tmp_mbs_buffer = NULL; + char *mbs_name = mbs_buffer; + + /* + * First figure out how long the string is. + * If the len argument is -1 we count the chars here. + */ + if (len == FIND_LENGTH) { + length = wslen(name); + } else { + length = len; + } + + Wstring ws; + ws.init(name, length); + if (length >= MAXPATHLEN) { + mbs_name = tmp_mbs_buffer = getmem((length * MB_LEN_MAX) + 1); + } + (void) wcstombs(mbs_name, ws.get_string(), (length * MB_LEN_MAX) + 1); + + /* Look for the string */ + if (dont_enter || (foundp != 0)) { + np = hashtab.lookup(mbs_name); + if (foundp != 0) { + *foundp = (np != 0) ? true : false; + } + if ((np != 0) || dont_enter) { + if(tmp_mbs_buffer != NULL) { + retmem_mb(tmp_mbs_buffer); + } + return np; + } else { + np = ALLOC(Name); + } + } else { + Boolean found; + np = hashtab.insert(mbs_name, found); + if (found) { + if(tmp_mbs_buffer != NULL) { + retmem_mb(tmp_mbs_buffer); + } + return np; + } + } + getname_struct_count += sizeof(struct _Name); + *np = empty_Name; + + np->string_mb = strdup(mbs_name); + if(tmp_mbs_buffer != NULL) { + retmem_mb(tmp_mbs_buffer); + mbs_name = tmp_mbs_buffer = NULL; + } + getname_bytes_count += strlen(np->string_mb) + 1; + /* Fill in the new Name */ + np->stat.time = file_no_time; + np->hash.length = length; + /* Scan the namestring to classify it */ + for (cap = name, len = 0; --length >= 0;) { + len |= get_char_semantics_value(*cap++); + } + np->dollar = BOOLEAN((len & (int) dollar_sem) != 0); + np->meta = BOOLEAN((len & (int) meta_sem) != 0); + np->percent = BOOLEAN((len & (int) percent_sem) != 0); + np->wildcard = BOOLEAN((len & (int) wildcard_sem) != 0); + np->colon = BOOLEAN((len & (int) colon_sem) != 0); + np->parenleft = BOOLEAN((len & (int) parenleft_sem) != 0); + getname_names_count++; + return np; +} + +void +store_name(Name name) +{ + hashtab.insert(name); +} + +void +free_name(Name name) +{ + freename_names_count++; + freename_struct_count += sizeof(struct _Name); + freename_bytes_count += strlen(name->string_mb) + 1; + retmem_mb(name->string_mb); + for (Property next, p = name->prop; p != NULL; p = next) { + next = p->next; + free(p); + } + free(name); +} + +/* + * enable_interrupt(handler) + * + * This routine sets a new interrupt handler for the signals make + * wants to deal with. + * + * Parameters: + * handler The function installed as interrupt handler + * + * Static variables used: + * sigivalue The original signal handler + * sigqvalue The original signal handler + * sigtvalue The original signal handler + * sighvalue The original signal handler + */ +void +enable_interrupt(register void (*handler) (int)) +{ +#ifdef SUN5_0 + if (sigivalue != SIG_IGN) { +#else + if (sigivalue != (void (*) (int)) SIG_IGN) { +#endif + (void) bsd_signal(SIGINT, (SIG_PF) handler); + } +#ifdef SUN5_0 + if (sigqvalue != SIG_IGN) { +#else + if (sigqvalue != (void (*) (int)) SIG_IGN) { +#endif + (void) bsd_signal(SIGQUIT, (SIG_PF) handler); + } +#ifdef SUN5_0 + if (sigtvalue != SIG_IGN) { +#else + if (sigtvalue != (void (*) (int)) SIG_IGN) { +#endif + (void) bsd_signal(SIGTERM, (SIG_PF) handler); + } +#ifdef SUN5_0 + if (sighvalue != SIG_IGN) { +#else + if (sighvalue != (void (*) (int)) SIG_IGN) { +#endif + (void) bsd_signal(SIGHUP, (SIG_PF) handler); + } +} + +/* + * setup_char_semantics() + * + * Load the vector char_semantics[] with lexical markers + * + * Parameters: + * + * Global variables used: + * char_semantics The vector of character semantics that we set + */ +void +setup_char_semantics(void) +{ + char *s; + wchar_t wc_buffer[1]; + int entry; + + if (svr4) { + s = "@-"; + } else { + s = "=@-?!+"; + } + for (s; MBTOWC(wc_buffer, s); s++) { + entry = get_char_semantics_entry(*wc_buffer); + char_semantics[entry] |= (int) command_prefix_sem; + } + char_semantics[dollar_char_entry] |= (int) dollar_sem; + for (s = "#|=^();&<>*?[]:$`'\"\\\n"; MBTOWC(wc_buffer, s); s++) { + entry = get_char_semantics_entry(*wc_buffer); + char_semantics[entry] |= (int) meta_sem; + } + char_semantics[percent_char_entry] |= (int) percent_sem; + for (s = "@*<%?^"; MBTOWC(wc_buffer, s); s++) { + entry = get_char_semantics_entry(*wc_buffer); + char_semantics[entry] |= (int) special_macro_sem; + } + for (s = "?[*"; MBTOWC(wc_buffer, s); s++) { + entry = get_char_semantics_entry(*wc_buffer); + char_semantics[entry] |= (int) wildcard_sem; + } + char_semantics[colon_char_entry] |= (int) colon_sem; + char_semantics[parenleft_char_entry] |= (int) parenleft_sem; +} + +/* + * errmsg(errnum) + * + * Return the error message for a system call error + * + * Return value: + * An error message string + * + * Parameters: + * errnum The number of the error we want to describe + * + * Global variables used: + * sys_errlist A vector of error messages + * sys_nerr The size of sys_errlist + */ +char * +errmsg(int errnum) +{ +#ifdef linux + return strerror(errnum); +#else // linux + + extern int sys_nerr; +#ifdef SUN4_x + extern char *sys_errlist[]; +#endif + char *errbuf; + + if ((errnum < 0) || (errnum > sys_nerr)) { + errbuf = getmem(6+1+11+1); + (void) sprintf(errbuf, catgets(libmksdmsi18n_catd, 1, 127, "Error %d"), errnum); + return errbuf; + } else { +#ifdef SUN4_x + return(sys_errlist[errnum]); +#endif +#ifdef SUN5_0 + return strerror(errnum); +#endif + + } +#endif // linux +} + +static char static_buf[MAXPATHLEN*3]; + +/* + * fatal_mksh(format, args...) + * + * Print a message and die + * + * Parameters: + * format printf type format string + * args Arguments to match the format + */ +/*VARARGS*/ +void +fatal_mksh(char * message, ...) +{ + va_list args; + char *buf = static_buf; + char *mksh_fat_err = catgets(libmksdmsi18n_catd, 1, 128, "mksh: Fatal error: "); + char *cur_wrk_dir = catgets(libmksdmsi18n_catd, 1, 129, "Current working directory: "); + int mksh_fat_err_len = strlen(mksh_fat_err); + + va_start(args, message); + (void) fflush(stdout); + (void) strcpy(buf, mksh_fat_err); + size_t buf_len = vsnprintf(static_buf + mksh_fat_err_len, + sizeof(static_buf) - mksh_fat_err_len, + message, args) + + mksh_fat_err_len + + strlen(cur_wrk_dir) + + strlen(get_current_path_mksh()) + + 3; // "\n\n" + va_end(args); + if (buf_len >= sizeof(static_buf)) { + buf = getmem(buf_len); + (void) strcpy(buf, mksh_fat_err); + va_start(args, message); + (void) vsprintf(buf + mksh_fat_err_len, message, args); + va_end(args); + } + (void) strcat(buf, "\n"); +/* + if (report_pwd) { + */ + if (1) { + (void) strcat(buf, cur_wrk_dir); + (void) strcat(buf, get_current_path_mksh()); + (void) strcat(buf, "\n"); + } + (void) fputs(buf, stderr); + (void) fflush(stderr); + if (buf != static_buf) { + retmem_mb(buf); + } +#ifdef SUN5_0 + exit_status = 1; +#endif + exit(1); +} + +/* + * fatal_reader_mksh(format, args...) + * + * Parameters: + * format printf style format string + * args arguments to match the format + */ +/*VARARGS*/ +void +fatal_reader_mksh(char * pattern, ...) +{ + va_list args; + char message[1000]; + + va_start(args, pattern); +/* + if (file_being_read != NULL) { + WCSTOMBS(mbs_buffer, file_being_read); + if (line_number != 0) { + (void) sprintf(message, + catgets(libmksdmsi18n_catd, 1, 130, "%s, line %d: %s"), + mbs_buffer, + line_number, + pattern); + } else { + (void) sprintf(message, + "%s: %s", + mbs_buffer, + pattern); + } + pattern = message; + } + */ + + (void) fflush(stdout); + (void) fprintf(stderr, catgets(libmksdmsi18n_catd, 1, 131, "mksh: Fatal error in reader: ")); + (void) vfprintf(stderr, pattern, args); + (void) fprintf(stderr, "\n"); + va_end(args); + +/* + if (temp_file_name != NULL) { + (void) fprintf(stderr, + catgets(libmksdmsi18n_catd, 1, 132, "mksh: Temp-file %s not removed\n"), + temp_file_name->string_mb); + temp_file_name = NULL; + } + */ + +/* + if (report_pwd) { + */ + if (1) { + (void) fprintf(stderr, + catgets(libmksdmsi18n_catd, 1, 133, "Current working directory %s\n"), + get_current_path_mksh()); + } + (void) fflush(stderr); +#ifdef SUN5_0 + exit_status = 1; +#endif + exit(1); +} + +/* + * warning_mksh(format, args...) + * + * Print a message and continue. + * + * Parameters: + * format printf type format string + * args Arguments to match the format + */ +/*VARARGS*/ +void +warning_mksh(char * message, ...) +{ + va_list args; + + va_start(args, message); + (void) fflush(stdout); + (void) fprintf(stderr, catgets(libmksdmsi18n_catd, 1, 134, "mksh: Warning: ")); + (void) vfprintf(stderr, message, args); + (void) fprintf(stderr, "\n"); + va_end(args); +/* + if (report_pwd) { + */ + if (1) { + (void) fprintf(stderr, + catgets(libmksdmsi18n_catd, 1, 135, "Current working directory %s\n"), + get_current_path_mksh()); + } + (void) fflush(stderr); +} + +/* + * get_current_path_mksh() + * + * Stuff current_path with the current path if it isnt there already. + * + * Parameters: + * + * Global variables used: + */ +char * +get_current_path_mksh(void) +{ + char pwd[(MAXPATHLEN * MB_LEN_MAX)]; + static char *current_path; + + if (current_path == NULL) { +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + getcwd(pwd, sizeof(pwd)); +#else + (void) getwd(pwd); +#endif + if (pwd[0] == (int) nul_char) { + pwd[0] = (int) slash_char; + pwd[1] = (int) nul_char; + } + current_path = strdup(pwd); + } + return current_path; +} + +/* + * append_prop(target, type) + * + * Create a new property and append it to the property list of a Name. + * + * Return value: + * A new property block for the target + * + * Parameters: + * target The target that wants a new property + * type The type of property being requested + * + * Global variables used: + */ +Property +append_prop(register Name target, register Property_id type) +{ + register Property *insert = &target->prop; + register Property prop = *insert; + register int size; + + switch (type) { + case conditional_prop: + size = sizeof (struct Conditional); + break; + case line_prop: + size = sizeof (struct Line); + break; + case macro_prop: + size = sizeof (struct _Macro); + break; + case makefile_prop: + size = sizeof (struct Makefile); + break; + case member_prop: + size = sizeof (struct Member); + break; + case recursive_prop: + size = sizeof (struct Recursive); + break; + case sccs_prop: + size = sizeof (struct Sccs); + break; + case suffix_prop: + size = sizeof (struct Suffix); + break; + case target_prop: + size = sizeof (struct Target); + break; + case time_prop: + size = sizeof (struct STime); + break; + case vpath_alias_prop: + size = sizeof (struct Vpath_alias); + break; + case long_member_name_prop: + size = sizeof (struct Long_member_name); + break; + case macro_append_prop: + size = sizeof (struct _Macro_appendix); + break; + case env_mem_prop: + size = sizeof (struct _Env_mem); + break; + default: + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 136, "Internal error. Unknown prop type %d"), type); + } + for (; prop != NULL; insert = &prop->next, prop = *insert); + size += PROPERTY_HEAD_SIZE; + *insert = prop = (Property) getmem(size); + memset((char *) prop, 0, size); + prop->type = type; + prop->next = NULL; + return prop; +} + +/* + * maybe_append_prop(target, type) + * + * Append a property to the Name if none of this type exists + * else return the one already there + * + * Return value: + * A property of the requested type for the target + * + * Parameters: + * target The target that wants a new property + * type The type of property being requested + * + * Global variables used: + */ +Property +maybe_append_prop(register Name target, register Property_id type) +{ + register Property prop; + + if ((prop = get_prop(target->prop, type)) != NULL) { + return prop; + } + return append_prop(target, type); +} + +/* + * get_prop(start, type) + * + * Scan the property list of a Name to find the next property + * of a given type. + * + * Return value: + * The first property of the type, if any left + * + * Parameters: + * start The first property block to check for type + * type The type of property block we need + * + * Global variables used: + */ +Property +get_prop(register Property start, register Property_id type) +{ + for (; start != NULL; start = start->next) { + if (start->type == type) { + return start; + } + } + return NULL; +} + +/* + * append_string(from, to, length) + * + * Append a C string to a make string expanding it if nessecary + * + * Parameters: + * from The source (C style) string + * to The destination (make style) string + * length The length of the from string + * + * Global variables used: + */ +void +append_string(register wchar_t *from, register String to, register int length) +{ + if (length == FIND_LENGTH) { + length = wslen(from); + } + if (to->buffer.start == NULL) { + expand_string(to, 32 + length); + } + if (to->buffer.end - to->text.p <= length) { + expand_string(to, + (to->buffer.end - to->buffer.start) * 2 + + length); + } + if (length > 0) { + (void) wsncpy(to->text.p, from, length); + to->text.p += length; + } + *(to->text.p) = (int) nul_char; +} + +wchar_t * get_wstring(char *from) { + if(from == NULL) { + return NULL; + } + getwstring_count++; + wchar_t * wcbuf = ALLOC_WC(strlen(from) + 1); + mbstowcs(wcbuf, from, strlen(from)+1); + return wcbuf; +} + +void +append_string(register char *from, register String to, register int length) +{ + if (length == FIND_LENGTH) { + length = strlen(from); + } + if (to->buffer.start == NULL) { + expand_string(to, 32 + length); + } + if (to->buffer.end - to->text.p <= length) { + expand_string(to, + (to->buffer.end - to->buffer.start) * 2 + + length); + } + if (length > 0) { + (void) mbstowcs(to->text.p, from, length); + to->text.p += length; + } + *(to->text.p) = (int) nul_char; +} + +/* + * expand_string(string, length) + * + * Allocate more memory for strings that run out of space. + * + * Parameters: + * string The make style string we want to expand + * length The new length we need + * + * Global variables used: + */ +static void +expand_string(register String string, register int length) +{ + register wchar_t *p; + + if (string->buffer.start == NULL) { + /* For strings that have no memory allocated */ + string->buffer.start = + string->text.p = + string->text.end = + ALLOC_WC(length); + string->buffer.end = string->buffer.start + length; + string->text.p[0] = (int) nul_char; + string->free_after_use = true; + expandstring_count++; + return; + } + if (string->buffer.end - string->buffer.start >= length) { + /* If we really don't need more memory. */ + return; + } + /* + * Get more memory, copy the string and free the old buffer if + * it is was malloc()'ed. + */ + expandstring_count++; + p = ALLOC_WC(length); + (void) wscpy(p, string->buffer.start); + string->text.p = p + (string->text.p - string->buffer.start); + string->text.end = p + (string->text.end - string->buffer.start); + string->buffer.end = p + length; + if (string->free_after_use) { + retmem(string->buffer.start); + } + string->buffer.start = p; + string->free_after_use = true; +} + +/* + * append_char(from, to) + * + * Append one char to a make string expanding it if nessecary + * + * Parameters: + * from Single character to append to string + * to The destination (make style) string + * + * Global variables used: + */ +void +append_char(wchar_t from, register String to) +{ + if (to->buffer.start == NULL) { + expand_string(to, 32); + } + if (to->buffer.end - to->text.p <= 2) { + expand_string(to, to->buffer.end - to->buffer.start + 32); + } + *(to->text.p)++ = from; + *(to->text.p) = (int) nul_char; +} + +/* + * handle_interrupt_mksh() + * + * This is where C-C traps are caught. + */ +void +handle_interrupt_mksh(int) +{ + (void) fflush(stdout); + /* Make sure the processes running under us terminate first. */ + if (childPid > 0) { + kill(childPid, SIGTERM); + childPid = -1; + } +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + while (wait((int *) NULL) != -1); +#if defined(SUN5_0) + exit_status = 2; +#endif +#else + while (wait((union wait *) NULL) != -1); +#endif + exit(2); +} + +/* + * setup_interrupt() + * + * This routine saves the original interrupt handler pointers + * + * Parameters: + * + * Static variables used: + * sigivalue The original signal handler + * sigqvalue The original signal handler + * sigtvalue The original signal handler + * sighvalue The original signal handler + */ +void +setup_interrupt(register void (*handler) (int)) +{ +#ifdef SUN5_0 + sigivalue = bsd_signal(SIGINT, SIG_IGN); + sigqvalue = bsd_signal(SIGQUIT, SIG_IGN); + sigtvalue = bsd_signal(SIGTERM, SIG_IGN); + sighvalue = bsd_signal(SIGHUP, SIG_IGN); +#else + sigivalue = (void (*) (int)) bsd_signal(SIGINT, SIG_IGN); + sigqvalue = (void (*) (int)) bsd_signal(SIGQUIT, SIG_IGN); + sigtvalue = (void (*) (int)) bsd_signal(SIGTERM, SIG_IGN); + sighvalue = (void (*) (int)) bsd_signal(SIGHUP, SIG_IGN); +#endif + enable_interrupt(handler); +} + + +void +mbstowcs_with_check(wchar_t *pwcs, const char *s, size_t n) +{ + if(mbstowcs(pwcs, s, n) == -1) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 143, "The string `%s' is not valid in current locale"), s); + } +} + + + +Wstring::Wstring() +{ + INIT_STRING_FROM_STACK(string, string_buf); +} + +Wstring::Wstring(struct _Name * name) +{ + INIT_STRING_FROM_STACK(string, string_buf); + append_string(name->string_mb, &string, name->hash.length); +} + +Wstring::~Wstring() +{ + if(string.free_after_use) { + retmem(string.buffer.start); + } +} + +void +Wstring::init(struct _Name * name) +{ + if(string.free_after_use) { + retmem(string.buffer.start); + } + INIT_STRING_FROM_STACK(string, string_buf); + append_string(name->string_mb, &string, name->hash.length); +} + +void +Wstring::init(wchar_t * name, unsigned length) +{ + INIT_STRING_FROM_STACK(string, string_buf); + append_string(name, &string, length); + string.buffer.start[length] = 0; +} + +Boolean +Wstring::equaln(wchar_t * str, unsigned length) +{ + return (Boolean)IS_WEQUALN(string.buffer.start, str, length); +} + +Boolean +Wstring::equaln(Wstring * str, unsigned length) +{ + return (Boolean)IS_WEQUALN(string.buffer.start, str->string.buffer.start, length); +} + +Boolean +Wstring::equal(wchar_t * str, unsigned off, unsigned length) +{ + return (Boolean)IS_WEQUALN(string.buffer.start + off, str, length); +} + +Boolean +Wstring::equal(wchar_t * str, unsigned off) +{ + return (Boolean)IS_WEQUAL(string.buffer.start + off, str); +} + +Boolean +Wstring::equal(wchar_t * str) +{ + return equal(str, 0); +} + +Boolean +Wstring::equal(Wstring * str, unsigned off, unsigned length) +{ + return (Boolean)IS_WEQUALN(string.buffer.start + off, str->string.buffer.start, length); +} + +Boolean +Wstring::equal(Wstring * str) +{ + return equal(str, 0); +} + +Boolean +Wstring::equal(Wstring * str, unsigned off) +{ + return (Boolean)IS_WEQUAL(string.buffer.start + off, str->string.buffer.start); +} + +void +Wstring::append_to_str(struct _String * str, unsigned off, unsigned length) +{ + append_string(string.buffer.start + off, str, length); +} + +Name +Name_set::lookup(const char *key) +{ + for (entry *node = root; node != 0;) { + int res = strcmp(key, node->name->string_mb); + if (res < 0) { + node = node->left; + } else if (res > 0) { + node = node->right; + } else { + return node->name; + } + } + return 0; +} + +Name +Name_set::insert(const char *key, Boolean &found) +{ + Name name = 0; + + if (root != 0) { + for (entry *node = root; name == 0;) { + int res = strcmp(key, node->name->string_mb); + if (res < 0) { + if (node->left != 0) { + node = node->left; + } else { + found = false; + name = ALLOC(Name); + + node->left = new entry(name, node); + rebalance(node); + } + } else if (res > 0) { + if (node->right != 0) { + node = node->right; + } else { + found = false; + name = ALLOC(Name); + + node->right = new entry(name, node); + rebalance(node); + } + } else { + found = true; + name = node->name; + } + } + } else { + found = false; + name = ALLOC(Name); + + root = new entry(name, 0); + } + return name; +} + +void +Name_set::insert(Name name) { + if (root != 0) { + for (entry *node = root;;) { + int res = strcmp(name->string_mb, node->name->string_mb); + if (res < 0) { + if (node->left != 0) { + node = node->left; + } else { + node->left = new entry(name, node); + rebalance(node); + break; + } + } else if (res > 0) { + if (node->right != 0) { + node = node->right; + } else { + node->right = new entry(name, node); + rebalance(node); + break; + } + } else { + // should be an error: inserting already existing name + break; + } + } + } else { + root = new entry(name, 0); + } +} + +void +Name_set::rebalance(Name_set::entry *node) { + for (; node != 0; node = node->parent) { + entry *right = node->right; + entry *left = node->left; + + unsigned rdepth = (right != 0) ? right->depth : 0; + unsigned ldepth = (left != 0) ? left->depth : 0; + + if (ldepth > rdepth + 1) { + if ((node->left = left->right) != 0) { + left->right->parent = node; + } + if ((left->parent = node->parent) != 0) { + if (node == node->parent->right) { + node->parent->right = left; + } else { + node->parent->left = left; + } + } else { + root = left; + } + left->right = node; + node->parent = left; + + node->setup_depth(); + node = left; + } else if (rdepth > ldepth + 1) { + if ((node->right = right->left) != 0) { + right->left->parent = node; + } + if ((right->parent = node->parent) != 0) { + if (node == node->parent->right) { + node->parent->right = right; + } else { + node->parent->left = right; + } + } else { + root = right; + } + right->left = node; + node->parent = right; + + node->setup_depth(); + node = right; + } + node->setup_depth(); + } +} + +Name_set::iterator +Name_set::begin() const { + for (entry *node = root; node != 0; node = node->left) { + if (node->left == 0) { + return iterator(node); + } + } + return iterator(); +} + +Name_set::iterator& +Name_set::iterator::operator++() { + if (node != 0) { + if (node->right != 0) { + node = node->right; + while (node->left != 0) { + node = node->left; + } + } else { + while ((node->parent != 0) && (node->parent->right == node)) { + node = node->parent; + } + node = node->parent; + } + } + return *this; +} diff --git a/usr/src/make_src/Make/lib/mksh/src/mksh.cc b/usr/src/make_src/Make/lib/mksh/src/mksh.cc new file mode 100644 index 0000000..98c9601 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/mksh.cc @@ -0,0 +1,286 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)mksh.cc 1.22 06/12/12 + */ + +#pragma ident "@(#)mksh.cc 1.22 06/12/12" + +/* + * mksh.cc + * + * Execute the command(s) of one Make or DMake rule + */ + +/* + * Included files + */ +#if defined(TEAMWARE_MAKE_CMN) || defined(MAKETOOL) /* tolik */ +# include <avo/util.h> +#endif + +#include <mksh/dosys.h> /* redirect_io() */ +#include <mksh/misc.h> /* retmem() */ +#include <mksh/mksh.h> +#include <mksdmsi18n/mksdmsi18n.h> +#include <errno.h> +#include <signal.h> + +#ifdef HP_UX + extern void (*sigset(int, void (*)(__harg)))(__harg); +#endif + +/* + * Workaround for NFS bug. Sometimes, when running 'chdir' on a remote + * dmake server, it fails with "Stale NFS file handle" error. + * The second attempt seems to work. + */ +int +my_chdir(char * dir) { + int res = chdir(dir); + if (res != 0 && (errno == ESTALE || errno == EAGAIN)) { + /* Stale NFS file handle. Try again */ + res = chdir(dir); + } + return res; +} + + +/* + * File table of contents + */ +static void change_sunpro_dependencies_value(char *oldpath, char *newpath); +static void init_mksh_globals(char *shell); +static void set_env_vars(char *env_list[]); + +#if defined(DISTRIBUTED) || defined(MAKETOOL) /* tolik */ +/* + * Execute the command(s) of one Make or DMake rule + */ +int +do_job(Avo_DmakeCommand *cmd_list[], char *env_list[], char *stdout_file, char *stderr_file, char *cwd, char *cnwd, int ignore, int silent, pathpt vroot_path, char *shell, int nice_prio) +{ + Boolean always_exec_flag; + char *cmd; + Avo_DmakeCommand **cmd_list_p; + Name command; + Boolean do_not_exec_flag; + Boolean ignore_flag; + int length; + Boolean make_refd_flag; + Boolean meta_flag; + char pathname[MAXPATHLEN]; + Doname result; + Boolean silent_flag; + wchar_t *tmp_wcs_buffer; + + if ((childPid = fork()) < 0) { /* error */ + ; + } else if (childPid > 0) { /* parent */ + ; + } else { /* child, mksh */ + (void) sigset(SIGCHLD, SIG_DFL); + enable_interrupt(handle_interrupt_mksh); + /* set environment variables */ + set_env_vars(env_list); + /* redirect stdout and stderr to temp files */ + dup2(1, 2); // Because fatal_mksh() prints error messages into + // stderr but dmake uses stderr for XDR communications + // and stdout for errors messages. + redirect_io(stdout_file, stderr_file); + /* try cd'ing to cwd */ + if (my_chdir(cwd) != 0) { + /* try the netpath machine:pathname */ + if (!avo_netpath_to_path(cnwd, pathname)) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 137, "`cd %s' failed, and conversion of %s to automounter pathname also failed: %s"), cwd, cnwd, strerror(errno)); + } else if (my_chdir(pathname) != 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 138, "`cd %s' and `cd %s' both failed: %s"), cwd, pathname, strerror(errno)); + } + /* + * change the value of SUNPRO_DEPENDENCIES + * to the new path. + */ + change_sunpro_dependencies_value(cwd, pathname); + } + init_mksh_globals(shell); + for (cmd_list_p = cmd_list; + *cmd_list_p != (Avo_DmakeCommand *) NULL; + cmd_list_p++) { + if ((*cmd_list_p)->ignore()) { + ignore_flag = true; + } else { + ignore_flag = false; + } + if ((*cmd_list_p)->silent()) { + silent_flag = true; + } else { + silent_flag = false; + } +/* + if ((*cmd_list_p)->always_exec()) { + always_exec_flag = true; + } else { + always_exec_flag = false; + } + */ + always_exec_flag = false; + if ((*cmd_list_p)->meta()) { + meta_flag = true; + } else { + meta_flag = false; + } + if ((*cmd_list_p)->make_refd()) { + make_refd_flag = true; + } else { + make_refd_flag = false; + } + if ((*cmd_list_p)->do_not_exec()) { + do_not_exec_flag = true; + } else { + do_not_exec_flag = false; + } + do_not_exec_rule = do_not_exec_flag; + cmd = (*cmd_list_p)->getCmd(); + if ((length = strlen(cmd)) >= MAXPATHLEN) { + tmp_wcs_buffer = ALLOC_WC(length + 1); + (void) mbstowcs(tmp_wcs_buffer, cmd, length + 1); + command = GETNAME(tmp_wcs_buffer, FIND_LENGTH); + retmem(tmp_wcs_buffer); + } else { + MBSTOWCS(wcs_buffer, cmd); + command = GETNAME(wcs_buffer, FIND_LENGTH); + } + if ((command->hash.length > 0) && + (!silent_flag || do_not_exec_flag)) { + (void) printf("%s\n", command->string_mb); + } + result = dosys_mksh(command, + ignore_flag, + make_refd_flag, + false, /* bugs #4085164 & #4990057 */ + /* BOOLEAN(silent_flag && ignore_flag), */ + always_exec_flag, + (Name) NULL, + false, + NULL, + NULL, + vroot_path, + nice_prio); + if (result == build_failed) { + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in do_job(), and dosys_mksh() returned result of build_failed.")); +#endif + + if (silent_flag) { + (void) printf(catgets(libmksdmsi18n_catd, 1, 139, "The following command caused the error:\n%s\n"), + command->string_mb); + } + if (!ignore_flag && !ignore) { + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in do_job(), and dosys_mksh() returned result of build_failed, exiting 1.")); +#endif + + exit(1); + } + } + } + +#ifdef PRINT_EXIT_STATUS + warning_mksh(NOCATGETS("I'm in do_job(), exiting 0.")); +#endif + + exit(0); + } + return childPid; +} +#endif /* TEAMWARE_MAKE_CMN */ + +static void +set_env_vars(char *env_list[]) +{ + char **env_list_p; + + for (env_list_p = env_list; + *env_list_p != (char *) NULL; + env_list_p++) { + putenv(*env_list_p); + } +} + +static void +init_mksh_globals(char *shell) +{ +/* + MBSTOWCS(wcs_buffer, NOCATGETS("SHELL")); + shell_name = GETNAME(wcs_buffer, FIND_LENGTH); + MBSTOWCS(wcs_buffer, shell); + (void) SETVAR(shell_name, GETNAME(wcs_buffer, FIND_LENGTH), false); + */ + char * dmake_shell; + if ((dmake_shell = getenv(NOCATGETS("DMAKE_SHELL"))) == NULL) { + dmake_shell = shell; + } + MBSTOWCS(wcs_buffer, dmake_shell); + shell_name = GETNAME(wcs_buffer, FIND_LENGTH); +} + +/* + * Change the pathname in the value of the SUNPRO_DEPENDENCIES env variable + * from oldpath to newpath. + */ +static void +change_sunpro_dependencies_value(char *oldpath, char *newpath) +{ + char buf[MAXPATHLEN]; + static char *env; + int length; + int oldpathlen; + char *sp_dep_value; + + /* check if SUNPRO_DEPENDENCIES is set in the environment */ + if ((sp_dep_value = getenv(NOCATGETS("SUNPRO_DEPENDENCIES"))) != NULL) { + oldpathlen = strlen(oldpath); + /* check if oldpath is indeed in the value of SUNPRO_DEPENDENCIES */ + if (strncmp(oldpath, sp_dep_value, oldpathlen) == 0) { + (void) sprintf(buf, + "%s%s", + newpath, + sp_dep_value + oldpathlen); + length = 2 + + strlen(NOCATGETS("SUNPRO_DEPENDENCIES")) + + strlen(buf); + env = getmem(length); + (void) sprintf(env, + "%s=%s", + NOCATGETS("SUNPRO_DEPENDENCIES"), + buf); + (void) putenv(env); + } + } +} + + diff --git a/usr/src/make_src/Make/lib/mksh/src/read.cc b/usr/src/make_src/Make/lib/mksh/src/read.cc new file mode 100644 index 0000000..53cd524 --- /dev/null +++ b/usr/src/make_src/Make/lib/mksh/src/read.cc @@ -0,0 +1,174 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)read.cc 1.11 06/12/12 + */ + +#pragma ident "@(#)read.cc 1.11 06/12/12" + +/* + * read.c + * + * This file contains the makefile reader. + */ + +/* + * Included files + */ +#include <mksh/misc.h> /* retmem() */ +#include <mksh/read.h> +#include <mksdmsi18n/mksdmsi18n.h> +#include <sys/uio.h> /* read() */ +#include <unistd.h> /* close(), unlink(), read() */ + +#define STRING_LEN_TO_CONVERT (8*1024) + +/* + * get_next_block_fn(source) + * + * Will get the next block of text to read either + * by popping one source bVSIZEOFlock of the stack of Sources + * or by reading some more from the makefile. + * + * Return value: + * The new source block to read from + * + * Parameters: + * source The old source block + * + * Global variables used: + * file_being_read The name of the current file, error msg + */ +Boolean make_state_locked; +Source +get_next_block_fn(register Source source) +{ + register off_t to_read; + register int length; + register size_t num_wc_chars; + char ch_save; + char *ptr; + + if (source == NULL) { + return NULL; + } + if ((source->fd < 0) || + ((source->bytes_left_in_file <= 0) && + (source->inp_buf_ptr >= source->inp_buf_end))) { + /* We can't read from the makefile, so pop the source block */ + if (source->fd > 2) { + (void) close(source->fd); + if (make_state_lockfile != NULL) { + (void) unlink(make_state_lockfile); + retmem_mb(make_state_lockfile); + make_state_lockfile = NULL; + make_state_locked = false; + } + } + if (source->string.free_after_use && + (source->string.buffer.start != NULL)) { + retmem(source->string.buffer.start); + source->string.buffer.start = NULL; + } + if (source->inp_buf != NULL) { + retmem_mb(source->inp_buf); + source->inp_buf = NULL; + } + source = source->previous; + if (source != NULL) { + source->error_converting = false; + } + return source; + } + if (source->bytes_left_in_file > 0) { + /* + * Read the whole makefile. + * Hopefully the kernel managed to prefetch the stuff. + */ + to_read = source->bytes_left_in_file; + source->inp_buf_ptr = source->inp_buf = getmem(to_read + 1); + source->inp_buf_end = source->inp_buf + to_read; + length = read(source->fd, source->inp_buf, (unsigned int) to_read); + if (length != to_read) { + WCSTOMBS(mbs_buffer, file_being_read); + if (length == 0) { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 140, "Error reading `%s': Premature EOF"), + mbs_buffer); + } else { + fatal_mksh(catgets(libmksdmsi18n_catd, 1, 141, "Error reading `%s': %s"), + mbs_buffer, + errmsg(errno)); + } + } + *source->inp_buf_end = nul_char; + source->bytes_left_in_file = 0; + } + /* + * Try to convert the next piece. + */ + ptr = source->inp_buf_ptr + STRING_LEN_TO_CONVERT; + if (ptr > source->inp_buf_end) { + ptr = source->inp_buf_end; + } + for (num_wc_chars = 0; ptr > source->inp_buf_ptr; ptr--) { + ch_save = *ptr; + *ptr = nul_char; + num_wc_chars = mbstowcs(source->string.text.end, + source->inp_buf_ptr, + STRING_LEN_TO_CONVERT); + *ptr = ch_save; + if (num_wc_chars != (size_t)-1) { + break; + } + } + + if ((int) num_wc_chars == (size_t)-1) { + source->error_converting = true; + return source; + } + + source->error_converting = false; + source->inp_buf_ptr = ptr; + source->string.text.end += num_wc_chars; + *source->string.text.end = 0; + + if (source->inp_buf_ptr >= source->inp_buf_end) { + if (*(source->string.text.end - 1) != (int) newline_char) { + WCSTOMBS(mbs_buffer, file_being_read); + warning_mksh(catgets(libmksdmsi18n_catd, 1, 142, "newline is not last character in file %s"), + mbs_buffer); + *source->string.text.end++ = (int) newline_char; + *source->string.text.end = (int) nul_char; + *source->string.buffer.end++; + } + if (source->inp_buf != NULL) { + retmem_mb(source->inp_buf); + source->inp_buf = NULL; + } + } + return source; +} + + diff --git a/usr/src/make_src/Make/lib/vroot/Makefile b/usr/src/make_src/Make/lib/vroot/Makefile new file mode 100644 index 0000000..fd663cd --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/Makefile @@ -0,0 +1,29 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.5 06/12/12 +# + +TOP = ../../.. +include $(TOP)/rules/variant.mk +include $(TOP)/rules/derived.mk diff --git a/usr/src/make_src/Make/lib/vroot/src/Makefile b/usr/src/make_src/Make/lib/vroot/src/Makefile new file mode 100644 index 0000000..299c46d --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/Makefile @@ -0,0 +1,49 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.3 06/12/12 +# + +# Generic makefile for use in src directories. Knows how to make common things +# in the right $(VARIANT) directory. + +include $(TOP)/rules/variant.mk + +all := TARG = all +install := TARG = install +clean := TARG = clean +test := TARG = test +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +SRC = ../src +MFLAGS += SRC=$(SRC) + +# See $(TOP)/rules/master.mk for how these are built. +%.h %.cc %.C %.E %.o all install clean test l10n_install i18n_install: FRC + @ if [ ! -d ../$(VARIANT) ]; then \ + mkdir ../$(VARIANT) ; \ + fi + cd ../$(VARIANT); $(MAKE) $(MFLAGS) -f $(SRC)/Variant.mk DESTDIR=$(DESTDIR) $@ + +FRC: diff --git a/usr/src/make_src/Make/lib/vroot/src/Variant.mk b/usr/src/make_src/Make/lib/vroot/src/Variant.mk new file mode 100644 index 0000000..b276156 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/Variant.mk @@ -0,0 +1,71 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Variant.mk 1.28 06/12/12 +# + +TOP = ../../../.. +include $(TOP)/rules/master.mk +include $(TOP)/rules/dmake.mk + +PKG_TOP = $(TOP)/Make +CPPFLAGS += -I$(PKG_TOP)/include + +CCSRCS = \ + access.cc \ + args.cc \ + chdir.cc \ + chmod.cc \ + chown.cc \ + chroot.cc \ + creat.cc \ + execve.cc \ + lock.cc \ + lstat.cc \ + mkdir.cc \ + mount.cc \ + open.cc \ + readlink.cc \ + report.cc \ + rmdir.cc \ + stat.cc \ + statfs.cc \ + truncate.cc \ + unlink.cc \ + unmount.cc \ + utimes.cc \ + vroot.cc \ + setenv.cc + + +HDRS_DIR = $(PKG_TOP)/include/vroot + +.INIT: $(HDRS_DIR)/args.h $(HDRS_DIR)/report.h $(HDRS_DIR)/vroot.h + +LIBNAME = libvroot.a +MSG_FILE = libvroot.msg +I18N_DIRS = $(SRC) + +include $(TOP)/Make/lib/Lib.mk +include $(TOP)/rules/lib.mk + diff --git a/usr/src/make_src/Make/lib/vroot/src/access.cc b/usr/src/make_src/Make/lib/vroot/src/access.cc new file mode 100644 index 0000000..83141cc --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/access.cc @@ -0,0 +1,46 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)access.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)access.cc 1.4 06/12/12" + +#include <unistd.h> +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int access_thunk(char *path) +{ + vroot_result= access(path, vroot_args.access.mode); + return((vroot_result == 0) || (errno != ENOENT)); +} + +int access_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.access.mode= mode; + translate_with_thunk(path, access_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/args.cc b/usr/src/make_src/Make/lib/vroot/src/args.cc new file mode 100644 index 0000000..de4ad9b --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/args.cc @@ -0,0 +1,35 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)args.cc 1.3 06/12/12 + */ + +#pragma ident "@(#)args.cc 1.3 06/12/12" + +#include <vroot/vroot.h> +#include <vroot/args.h> + +union Args vroot_args; +int vroot_result; diff --git a/usr/src/make_src/Make/lib/vroot/src/chdir.cc b/usr/src/make_src/Make/lib/vroot/src/chdir.cc new file mode 100644 index 0000000..c5aa0ac --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/chdir.cc @@ -0,0 +1,45 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)chdir.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)chdir.cc 1.4 06/12/12" + +#include <unistd.h> +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int chdir_thunk(char *path) +{ + vroot_result= chdir(path); + return(vroot_result == 0); +} + +int chdir_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot) +{ + translate_with_thunk(path, chdir_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/chmod.cc b/usr/src/make_src/Make/lib/vroot/src/chmod.cc new file mode 100644 index 0000000..64cda72 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/chmod.cc @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)chmod.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)chmod.cc 1.4 06/12/12" + +#include <sys/types.h> +#include <sys/stat.h> + +extern int chmod(const char *path, mode_t mode); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int chmod_thunk(char *path) +{ + vroot_result= chmod(path, vroot_args.chmod.mode); + return(vroot_result == 0); +} + +int chmod_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.chmod.mode= mode; + translate_with_thunk(path, chmod_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/chown.cc b/usr/src/make_src/Make/lib/vroot/src/chown.cc new file mode 100644 index 0000000..eeeb2ef --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/chown.cc @@ -0,0 +1,51 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)chown.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)chown.cc 1.4 06/12/12" + +#include <unistd.h> +#include <sys/types.h> + +extern int chown(const char *path, uid_t owner, gid_t group); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int chown_thunk(char *path) +{ + vroot_result= chown(path, vroot_args.chown.user, vroot_args.chown.group); + return(vroot_result == 0); +} + +int chown_vroot(char *path, int user, int group, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.chown.user= user; + vroot_args.chown.group= group; + translate_with_thunk(path, chown_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/chroot.cc b/usr/src/make_src/Make/lib/vroot/src/chroot.cc new file mode 100644 index 0000000..8586a8c --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/chroot.cc @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)chroot.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)chroot.cc 1.4 06/12/12" + +#include <unistd.h> + +extern int chroot(const char *path); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int chroot_thunk(char *path) +{ + vroot_result= chroot(path); + return(vroot_result == 0); +} + +int chroot_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot) +{ + translate_with_thunk(path, chroot_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/creat.cc b/usr/src/make_src/Make/lib/vroot/src/creat.cc new file mode 100644 index 0000000..27aa694 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/creat.cc @@ -0,0 +1,51 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)creat.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)creat.cc 1.4 06/12/12" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +extern int creat(const char *path, mode_t mode); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int creat_thunk(char *path) +{ + vroot_result= creat(path, vroot_args.creat.mode); + return(vroot_result >= 0); +} + +int creat_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.creat.mode= mode; + translate_with_thunk(path, creat_thunk, vroot_path, vroot_vroot, rw_write); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/execve.cc b/usr/src/make_src/Make/lib/vroot/src/execve.cc new file mode 100644 index 0000000..ec2a268 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/execve.cc @@ -0,0 +1,54 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)execve.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)execve.cc 1.4 06/12/12" + +#include <unistd.h> + +extern int execve (const char *path, char *const argv[], char *const envp[]); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int execve_thunk(char *path) +{ + execve(path, vroot_args.execve.argv, vroot_args.execve.environ); + switch (errno) { + case ETXTBSY: + case ENOEXEC: return 1; + default: return 0; + } +} + +int execve_vroot(char *path, char **argv, char **environ, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.execve.argv= argv; + vroot_args.execve.environ= environ; + translate_with_thunk(path, execve_thunk, vroot_path, vroot_vroot, rw_read); + return(-1); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/libvroot.msg b/usr/src/make_src/Make/lib/vroot/src/libvroot.msg new file mode 100644 index 0000000..f3a805f --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/libvroot.msg @@ -0,0 +1,38 @@ + +$quote " + + +$set 1 +$ +$ CDDL HEADER START +$ +$ The contents of this file are subject to the terms of the +$ Common Development and Distribution License (the "License"). +$ You may not use this file except in compliance with the License. +$ +$ You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +$ or http://www.opensolaris.org/os/licensing. +$ See the License for the specific language governing permissions +$ and limitations under the License. +$ +$ When distributing Covered Code, include this CDDL HEADER in each +$ file and include the License file at usr/src/OPENSOLARIS.LICENSE. +$ If applicable, add the following below this CDDL HEADER, with the +$ fields enclosed by brackets "[]" replaced with your own identifying +$ information: Portions Copyright [yyyy] [name of copyright owner] +$ +$ CDDL HEADER END +$ +$ Copyright 1996 Sun Microsystems, Inc. All rights reserved. +$ Use is subject to license terms. +$ +$ @(#)libvroot.msg 1.2 06/12/12 +$ +142 "file_lock: file %s is already locked.\n" +143 "file_lock: will periodically check the lockfile %s for two minutes.\n" +144 "Current working directory %s\n" +145 "Could not lock file `%s'; " +146 " failed - " +147 "Couldn't write to %s" +148 "Cannot open `%s' for writing\n" +149 "Cannot open %s for writing\n" diff --git a/usr/src/make_src/Make/lib/vroot/src/lock.cc b/usr/src/make_src/Make/lib/vroot/src/lock.cc new file mode 100644 index 0000000..ca5a9a5 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/lock.cc @@ -0,0 +1,196 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)lock.cc 1.17 06/12/12 + */ + +#pragma ident "@(#)lock.cc 1.17 06/12/12" + +#include <avo/intl.h> /* for NOCATGETS */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/errno.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <vroot/vroot.h> +#include <mksdmsi18n/mksdmsi18n.h> +#include <signal.h> +#include <errno.h> /* errno */ + +#if !defined(linux) +extern char *sys_errlist[]; +extern int sys_nerr; +#endif + +static void file_lock_error(char *msg, char *file, char *str, int arg1, int arg2); + +#define BLOCK_INTERUPTS sigfillset(&newset) ; \ + sigprocmask(SIG_SETMASK, &newset, &oldset) + +#define UNBLOCK_INTERUPTS \ + sigprocmask(SIG_SETMASK, &oldset, &newset) + +/* + * This code stolen from the NSE library and changed to not depend + * upon any NSE routines or header files. + * + * Simple file locking. + * Create a symlink to a file. The "test and set" will be + * atomic as creating the symlink provides both functions. + * + * The timeout value specifies how long to wait for stale locks + * to disappear. If the lock is more than 'timeout' seconds old + * then it is ok to blow it away. This part has a small window + * of vunerability as the operations of testing the time, + * removing the lock and creating a new one are not atomic. + * It would be possible for two processes to both decide to blow + * away the lock and then have process A remove the lock and establish + * its own, and then then have process B remove the lock which accidentily + * removes A's lock rather than the stale one. + * + * A further complication is with the NFS. If the file in question is + * being served by an NFS server, then its time is set by that server. + * We can not use the time on the client machine to check for a stale + * lock. Therefore, a temp file on the server is created to get + * the servers current time. + * + * Returns an error message. NULL return means the lock was obtained. + * + * 12/6/91 Added the parameter "file_locked". Before this parameter + * was added, the calling procedure would have to wait for file_lock() + * to return before it sets the flag. If the user interrupted "make" + * between the time the lock was acquired and the time file_lock() + * returns, make wouldn't know that the file has been locked, and therefore + * it wouldn' remove the lock. Setting the flag right after locking the file + * makes this window much smaller. + */ + +int +file_lock(char *name, char *lockname, int *file_locked, int timeout) +{ + int counter = 0; + static char msg[MAXPATHLEN+1]; + int printed_warning = 0; + int r; + struct stat statb; + sigset_t newset; + sigset_t oldset; + + *file_locked = 0; + if (timeout <= 0) { + timeout = 120; + } + for (;;) { + BLOCK_INTERUPTS; + r = symlink(name, lockname); + if (r == 0) { + *file_locked = 1; + UNBLOCK_INTERUPTS; + return 0; /* success */ + } + UNBLOCK_INTERUPTS; + + if (errno != EEXIST) { + file_lock_error(msg, name, NOCATGETS("symlink(%s, %s)"), + (int) name, (int) lockname); + fprintf(stderr, "%s", msg); + return errno; + } + + counter = 0; + for (;;) { + sleep(1); + r = lstat(lockname, &statb); + if (r == -1) { + /* + * The lock must have just gone away - try + * again. + */ + break; + } + + if ((counter > 5) && (!printed_warning)) { + /* Print waiting message after 5 secs */ +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + (void) getcwd(msg, MAXPATHLEN); +#else + (void) getwd(msg); +#endif + fprintf(stderr, + catgets(libmksdmsi18n_catd, 1, 162, "file_lock: file %s is already locked.\n"), + name); + fprintf(stderr, + catgets(libmksdmsi18n_catd, 1, 163, "file_lock: will periodically check the lockfile %s for two minutes.\n"), + lockname); + fprintf(stderr, + catgets(libmksdmsi18n_catd, 1, 144, "Current working directory %s\n"), + msg); + + printed_warning = 1; + } + + if (++counter > timeout ) { + /* + * Waited enough - return an error.. + */ + return EEXIST; + } + } + } + /* NOTREACHED */ +} + +/* + * Format a message telling why the lock could not be created. + */ +static void +file_lock_error(char *msg, char *file, char *str, int arg1, int arg2) +{ + int len; + + sprintf(msg, catgets(libmksdmsi18n_catd, 1, 145, "Could not lock file `%s'; "), file); + len = strlen(msg); + sprintf(&msg[len], str, arg1, arg2); + strcat(msg, catgets(libmksdmsi18n_catd, 1, 146, " failed - ")); +#if !defined(linux) + if (errno < sys_nerr) { +#ifdef SUN4_x + strcat(msg, sys_errlist[errno]); +#endif +#ifdef SUN5_0 + strcat(msg, strerror(errno)); +#endif + } else { + len = strlen(msg); + sprintf(&msg[len], NOCATGETS("errno %d"), errno); + } +#else + strcat(msg, strerror(errno)); +#endif +} + diff --git a/usr/src/make_src/Make/lib/vroot/src/lstat.cc b/usr/src/make_src/Make/lib/vroot/src/lstat.cc new file mode 100644 index 0000000..ba938aa --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/lstat.cc @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1998 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)lstat.cc 1.6 06/12/12 + */ + +#pragma ident "@(#)lstat.cc 1.6 06/12/12" + +#include <sys/types.h> +#include <sys/stat.h> + +extern int lstat(const char *path, struct stat *buf); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int lstat_thunk(char *path) +{ + vroot_result= lstat(path, vroot_args.lstat.buffer); + return(vroot_result == 0); +} + +int lstat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.lstat.buffer= buffer; + translate_with_thunk(path, lstat_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/mkdir.cc b/usr/src/make_src/Make/lib/vroot/src/mkdir.cc new file mode 100644 index 0000000..7180039 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/mkdir.cc @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)mkdir.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)mkdir.cc 1.4 06/12/12" + +#include <sys/types.h> +#include <sys/stat.h> + +extern int mkdir(const char *path, mode_t mode); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int mkdir_thunk(char *path) +{ + vroot_result= mkdir(path, vroot_args.mkdir.mode); + return(vroot_result == 0); +} + +int mkdir_vroot(char *path, int mode, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.mkdir.mode= mode; + translate_with_thunk(path, mkdir_thunk, vroot_path, vroot_vroot, rw_write); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/mount.cc b/usr/src/make_src/Make/lib/vroot/src/mount.cc new file mode 100644 index 0000000..2769a55 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/mount.cc @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1995 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)mount.cc 1.5 06/12/12 + */ + +#pragma ident "@(#)mount.cc 1.5 06/12/12" + +#include <sys/types.h> +#include <sys/mount.h> + +#ifndef HP_UX +extern int mount(const char *spec, const char *dir, int mflag, ...); +#endif + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int mount_thunk(char *path) +{ + vroot_result= mount(path, vroot_args.mount.name, vroot_args.mount.mode); + return(vroot_result == 0); +} + +int mount_vroot(char *target, char *name, int mode, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.mount.name= name; + vroot_args.mount.mode= mode; + translate_with_thunk(target, mount_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/open.cc b/usr/src/make_src/Make/lib/vroot/src/open.cc new file mode 100644 index 0000000..30b44e6 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/open.cc @@ -0,0 +1,53 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)open.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)open.cc 1.4 06/12/12" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +extern int open(const char *path, int oflag, ...); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int open_thunk(char *path) +{ + vroot_result= open(path, vroot_args.open.flags, vroot_args.open.mode); + return(vroot_result >= 0); +} + +int open_vroot(char *path, int flags, int mode, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.open.flags= flags; + vroot_args.open.mode= mode; + translate_with_thunk(path, open_thunk, vroot_path, vroot_vroot, + ((flags & (O_CREAT|O_APPEND)) != 0) ? rw_write : rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/readlink.cc b/usr/src/make_src/Make/lib/vroot/src/readlink.cc new file mode 100644 index 0000000..e0efe5b --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/readlink.cc @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)readlink.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)readlink.cc 1.4 06/12/12" + +#include <unistd.h> + +extern int readlink(const char *path, void *buf, size_t bufsiz); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int readlink_thunk(char *path) +{ + vroot_result= readlink(path, vroot_args.readlink.buffer, vroot_args.readlink.buffer_size); + return(vroot_result >= 0); +} + +int readlink_vroot(char *path, char *buffer, int buffer_size, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.readlink.buffer= buffer; + vroot_args.readlink.buffer_size= buffer_size; + translate_with_thunk(path, readlink_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/report.cc b/usr/src/make_src/Make/lib/vroot/src/report.cc new file mode 100644 index 0000000..192eb13 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/report.cc @@ -0,0 +1,396 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)report.cc 1.17 06/12/12 + */ + +#pragma ident "@(#)report.cc 1.17 06/12/12" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/param.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <vroot/report.h> +#include <vroot/vroot.h> +#include <mksdmsi18n/mksdmsi18n.h> +#include <avo/intl.h> /* for NOCATGETS */ +#include <mk/defs.h> /* for tmpdir */ + +static FILE *report_file; +static FILE *command_output_fp; +static char *target_being_reported_for; +static char *search_dir; +static char command_output_tmpfile[30]; +static int is_path = 0; +static char sfile[MAXPATHLEN]; +extern "C" { +static void (*warning_ptr) (char *, ...) = (void (*) (char *, ...)) NULL; +} + +FILE * +get_report_file(void) +{ + return(report_file); +} + +char * +get_target_being_reported_for(void) +{ + return(target_being_reported_for); +} + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) +extern "C" { +static void +close_report_file(void) +{ + (void)fputs("\n", report_file); + (void)fclose(report_file); +} +} // extern "C" +#else +static void +close_report_file(int, ...) +{ + (void)fputs("\n", report_file); + (void)fclose(report_file); +} +#endif + +static void +clean_up(FILE *nse_depinfo_fp, FILE *merge_fp, char *nse_depinfo_file, char *merge_file, int unlinkf) +{ + fclose(nse_depinfo_fp); + fclose(merge_fp); + fclose(command_output_fp); + unlink(command_output_tmpfile); + if (unlinkf) + unlink(merge_file); + else + rename(merge_file, nse_depinfo_file); +} + + +/* + * Update the file, if necessary. We don't want to rewrite + * the file if we don't have to because we don't want the time of the file + * to change in that case. + */ + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) +extern "C" { +static void +close_file(void) +#else +static void +close_file(int, ...) +#endif +{ + char line[MAXPATHLEN+2]; + char buf[MAXPATHLEN+2]; + FILE *nse_depinfo_fp; + FILE *merge_fp; + char nse_depinfo_file[MAXPATHLEN]; + char merge_file[MAXPATHLEN]; + char lock_file[MAXPATHLEN]; + int err; + int len; + int changed = 0; + int file_locked; + + fprintf(command_output_fp, "\n"); + fclose(command_output_fp); + if ((command_output_fp = fopen(command_output_tmpfile, "r")) == NULL) { + return; + } + sprintf(nse_depinfo_file, "%s/%s", search_dir, NSE_DEPINFO); + sprintf(merge_file, NOCATGETS("%s/.tmp%s.%d"), search_dir, NSE_DEPINFO, getpid()); + sprintf(lock_file, "%s/%s", search_dir, NSE_DEPINFO_LOCK); + err = file_lock(nse_depinfo_file, lock_file, &file_locked, 0); + if (err) { + if (warning_ptr != (void (*) (char *, ...)) NULL) { + (*warning_ptr)(catgets(libmksdmsi18n_catd, 1, 147, "Couldn't write to %s"), nse_depinfo_file); + } + unlink(command_output_tmpfile); + return; + } + /* If .nse_depinfo file doesn't exist */ + if ((nse_depinfo_fp = fopen(nse_depinfo_file, "r+")) == NULL) { + if (is_path) { + if ((nse_depinfo_fp = + fopen(nse_depinfo_file, "w")) == NULL) { + fprintf(stderr, catgets(libmksdmsi18n_catd, 1, 148, "Cannot open `%s' for writing\n"), + nse_depinfo_file); + unlink(command_output_tmpfile); + + unlink(lock_file); + return; + } + while (fgets(line, MAXPATHLEN+2, command_output_fp) + != NULL) { + fprintf(nse_depinfo_fp, "%s", line); + } + fclose(command_output_fp); + } + fclose(nse_depinfo_fp); + if (file_locked) { + unlink(lock_file); + } + unlink(command_output_tmpfile); + return; + } + if ((merge_fp = fopen(merge_file, "w")) == NULL) { + fprintf(stderr, catgets(libmksdmsi18n_catd, 1, 149, "Cannot open %s for writing\n"), merge_file); + if (file_locked) { + unlink(lock_file); + } + unlink(command_output_tmpfile); + return; + } + len = strlen(sfile); + while (fgets(line, MAXPATHLEN+2, nse_depinfo_fp) != NULL) { + if (strncmp(line, sfile, len) == 0 && line[len] == ':') { + while (fgets(buf, MAXPATHLEN+2, command_output_fp) + != NULL) { + if (is_path) { + fprintf(merge_fp, "%s", buf); + if (strcmp(line, buf)) { + /* changed */ + changed = 1; + } + } + if (buf[strlen(buf)-1] == '\n') { + break; + } + } + if (changed || !is_path) { + while (fgets(line, MAXPATHLEN, nse_depinfo_fp) + != NULL) { + fputs(line, merge_fp); + } + clean_up(nse_depinfo_fp, merge_fp, + nse_depinfo_file, merge_file, 0); + } else { + clean_up(nse_depinfo_fp, merge_fp, + nse_depinfo_file, merge_file, 1); + } + if (file_locked) { + unlink(lock_file); + } + unlink(command_output_tmpfile); + return; + } /* entry found */ + fputs(line, merge_fp); + } + /* Entry never found. Add it if there is a search path */ + if (is_path) { + while (fgets(line, MAXPATHLEN+2, command_output_fp) != NULL) { + fprintf(nse_depinfo_fp, "%s", line); + } + } + clean_up(nse_depinfo_fp, merge_fp, nse_depinfo_file, merge_file, 1); + if (file_locked) { + unlink(lock_file); + } +} + +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) +} // extern "C" +#endif + +static void +report_dep(char *iflag, char *filename) +{ + + if (command_output_fp == NULL) { + sprintf(command_output_tmpfile, + NOCATGETS("%s/%s.%d.XXXXXX"), tmpdir, NSE_DEPINFO, getpid()); + int fd = mkstemp(command_output_tmpfile); + if ((fd < 0) || (command_output_fp = fdopen(fd, "w")) == NULL) { + return; + } + if ((search_dir = getenv(NOCATGETS("NSE_DEP"))) == NULL) { + return; + } +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + atexit(close_file); +#else + on_exit(close_file, 0); +#endif + strcpy(sfile, filename); + if (iflag == NULL || *iflag == '\0') { + return; + } + fprintf(command_output_fp, "%s:", sfile); + } + fprintf(command_output_fp, " "); + fprintf(command_output_fp, iflag); + if (iflag != NULL) { + is_path = 1; + } +} + +void +report_libdep(char *lib, char *flag) +{ + char *ptr; + char filename[MAXPATHLEN]; + char *p; + + if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) { + return; + } + ptr = strchr(p, ' '); + if(ptr) { + sprintf(filename, "%s-%s", ptr+1, flag); + is_path = 1; + report_dep(lib, filename); + } +} + +void +report_search_path(char *iflag) +{ + char curdir[MAXPATHLEN]; + char *sdir; + char *newiflag; + char filename[MAXPATHLEN]; + char *p, *ptr; + + if ((sdir = getenv(NOCATGETS("NSE_DEP"))) == NULL) { + return; + } + if ((p= getenv(SUNPRO_DEPENDENCIES)) == NULL) { + return; + } + ptr = strchr(p, ' '); + if( ! ptr ) { + return; + } + sprintf(filename, NOCATGETS("%s-CPP"), ptr+1); +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + getcwd(curdir, sizeof(curdir)); +#else + getwd(curdir); +#endif + if (strcmp(curdir, sdir) != 0 && strlen(iflag) > 2 && + iflag[2] != '/') { + /* Makefile must have had an "cd xx; cc ..." */ + /* Modify the -I path to be relative to the cd */ + newiflag = (char *)malloc(strlen(iflag) + strlen(curdir) + 2); + sprintf(newiflag, "-%c%s/%s", iflag[1], curdir, &iflag[2]); + report_dep(newiflag, filename); + } else { + report_dep(iflag, filename); + } +} + +void +report_dependency(register char *name) +{ + register char *filename; + char buffer[MAXPATHLEN+1]; + register char *p; + register char *p2; + char nse_depinfo_file[MAXPATHLEN]; + + if (report_file == NULL) { + if ((filename= getenv(SUNPRO_DEPENDENCIES)) == NULL) { + report_file = (FILE *)-1; + return; + } + if (strlen(filename) == 0) { + report_file = (FILE *)-1; + return; + } + (void)strcpy(buffer, name); + name = buffer; + p = strchr(filename, ' '); + if(p) { + *p= 0; + } else { + report_file = (FILE *)-1; + return; + } + if ((report_file= fopen(filename, "a")) == NULL) { + if ((report_file= fopen(filename, "w")) == NULL) { + report_file= (FILE *)-1; + return; + } + } +#if defined(SUN5_0) || defined(HP_UX) || defined(linux) + atexit(close_report_file); +#else + (void)on_exit(close_report_file, (char *)report_file); +#endif + if ((p2= strchr(p+1, ' ')) != NULL) + *p2= 0; + target_being_reported_for= (char *)malloc((unsigned)(strlen(p+1)+1)); + (void)strcpy(target_being_reported_for, p+1); + (void)fputs(p+1, report_file); + (void)fputs(":", report_file); + *p= ' '; + if (p2 != NULL) + *p2= ' '; + } + if (report_file == (FILE *)-1) + return; + (void)fputs(name, report_file); + (void)fputs(" ", report_file); +} + +#ifdef MAKE_IT +void +make_it(filename) + register char *filename; +{ + register char *command; + register char *argv[6]; + register int pid; + union wait foo; + + if (getenv(SUNPRO_DEPENDENCIES) == NULL) return; + command= alloca(strlen(filename)+32); + (void)sprintf(command, NOCATGETS("make %s\n"), filename); + switch (pid= fork()) { + case 0: /* child */ + argv[0]= NOCATGETS("csh"); + argv[1]= NOCATGETS("-c"); + argv[2]= command; + argv[3]= 0; + (void)dup2(2, 1); + execve(NOCATGETS("/bin/sh"), argv, environ); + perror(NOCATGETS("execve error")); + exit(1); + case -1: /* error */ + perror(NOCATGETS("fork error")); + default: /* parent */ + while (wait(&foo) != pid);}; +} +#endif + diff --git a/usr/src/make_src/Make/lib/vroot/src/rmdir.cc b/usr/src/make_src/Make/lib/vroot/src/rmdir.cc new file mode 100644 index 0000000..48a9a6b --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/rmdir.cc @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)rmdir.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)rmdir.cc 1.4 06/12/12" + +#include <unistd.h> + +extern int rmdir(const char *path); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int rmdir_thunk(char *path) +{ + vroot_result= rmdir(path); + return(vroot_result == 0); +} + +int rmdir_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot) +{ + translate_with_thunk(path, rmdir_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/setenv.cc b/usr/src/make_src/Make/lib/vroot/src/setenv.cc new file mode 100644 index 0000000..dc135e7 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/setenv.cc @@ -0,0 +1,65 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1994 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)setenv.cc 1.6 06/12/12 + */ + +#pragma ident "@(#)setenv.cc 1.6 06/12/12" + +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +extern char **environ; + +static short setenv_made_new_vector= 0; + +char *setenv(char *name, char *value) +{ char *p= NULL, **q; + int length= 0, vl; + + if ((p= getenv(name)) == NULL) { /* Allocate new vector */ + for (q= environ; *q != NULL; q++, length++); + q= (char **)malloc((unsigned)(sizeof(char *)*(length+2))); + memcpy(((char *)q)+sizeof(char *), (char *)environ, sizeof(char *)*(length+1)); + if (setenv_made_new_vector++) + free((char *)environ); + length= strlen(name); + environ= q;} + else { /* Find old slot */ + length= strlen(name); + for (q= environ; *q != NULL; q++) + if (!strncmp(*q, name, length)) + break;}; + vl= strlen(value); + if (!p || (length+vl+1 > strlen(p))) + *q= p= (char *) malloc((unsigned)(length+vl+2)); + else + p= *q; + (void)strcpy(p, name); p+= length; + *p++= '='; + (void)strcpy(p, value); + return(value); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/stat.cc b/usr/src/make_src/Make/lib/vroot/src/stat.cc new file mode 100644 index 0000000..475a851 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/stat.cc @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1998 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)stat.cc 1.6 06/12/12 + */ + +#pragma ident "@(#)stat.cc 1.6 06/12/12" + +#include <sys/types.h> +#include <sys/stat.h> + +extern int stat(const char *path, struct stat *buf); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int stat_thunk(char *path) +{ + vroot_result= stat(path, vroot_args.stat.buffer); + return(vroot_result == 0); +} + +int stat_vroot(char *path, struct stat *buffer, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.stat.buffer= buffer; + translate_with_thunk(path, stat_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/statfs.cc b/usr/src/make_src/Make/lib/vroot/src/statfs.cc new file mode 100644 index 0000000..ff8ac36 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/statfs.cc @@ -0,0 +1,49 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)statfs.cc 1.5 06/12/12 + */ + +#pragma ident "@(#)statfs.cc 1.5 06/12/12" + +#ifndef SUN5_0 + +#include <vroot/vroot.h> +#include <vroot/args.h> +#include <sys/vfs.h> + +static int statfs_thunk(char *path) +{ + vroot_result= statfs(path, vroot_args.statfs.buffer); + return(vroot_result == 0); +} + +int statfs_vroot(char *path, struct statfs *buffer, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.statfs.buffer= buffer; + translate_with_thunk(path, statfs_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} +#endif diff --git a/usr/src/make_src/Make/lib/vroot/src/truncate.cc b/usr/src/make_src/Make/lib/vroot/src/truncate.cc new file mode 100644 index 0000000..d38aa37 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/truncate.cc @@ -0,0 +1,49 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)truncate.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)truncate.cc 1.4 06/12/12" + +#include <unistd.h> + +extern int truncate(const char *path, off_t length); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int truncate_thunk(char *path) +{ + vroot_result= truncate(path, vroot_args.truncate.length); + return(vroot_result == 0); +} + +int truncate_vroot(char *path, int length, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.truncate.length= length; + translate_with_thunk(path, truncate_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/unlink.cc b/usr/src/make_src/Make/lib/vroot/src/unlink.cc new file mode 100644 index 0000000..71ae091 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/unlink.cc @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)unlink.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)unlink.cc 1.4 06/12/12" + +#include <unistd.h> + +extern int unlink(const char *path); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int unlink_thunk(char *path) +{ + vroot_result= unlink(path); + return(vroot_result == 0); +} + +int unlink_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot) +{ + translate_with_thunk(path, unlink_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/unmount.cc b/usr/src/make_src/Make/lib/vroot/src/unmount.cc new file mode 100644 index 0000000..e90d321 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/unmount.cc @@ -0,0 +1,48 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)unmount.cc 1.5 06/12/12 + */ + +#pragma ident "@(#)unmount.cc 1.5 06/12/12" + +#ifndef SUN5_0 +#include <vroot/vroot.h> +#include <vroot/args.h> + +extern int unmount(char *name); + +static int unmount_thunk(char *path) +{ + vroot_result= unmount(path); + return(vroot_result == 0); +} + +int unmount_vroot(char *path, pathpt vroot_path, pathpt vroot_vroot) +{ + translate_with_thunk(path, unmount_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} +#endif diff --git a/usr/src/make_src/Make/lib/vroot/src/utimes.cc b/usr/src/make_src/Make/lib/vroot/src/utimes.cc new file mode 100644 index 0000000..4f670b7 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/utimes.cc @@ -0,0 +1,50 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1993 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)utimes.cc 1.4 06/12/12 + */ + +#pragma ident "@(#)utimes.cc 1.4 06/12/12" + +#include <sys/types.h> +#include <sys/time.h> + +extern int utimes(char *file, struct timeval *tvp); + +#include <vroot/vroot.h> +#include <vroot/args.h> + +static int utimes_thunk(char *path) +{ + vroot_result= utimes(path, vroot_args.utimes.time); + return(vroot_result == 0); +} + +int utimes_vroot(char *path, struct timeval *time, pathpt vroot_path, pathpt vroot_vroot) +{ + vroot_args.utimes.time= time; + translate_with_thunk(path, utimes_thunk, vroot_path, vroot_vroot, rw_read); + return(vroot_result); +} diff --git a/usr/src/make_src/Make/lib/vroot/src/vroot.cc b/usr/src/make_src/Make/lib/vroot/src/vroot.cc new file mode 100644 index 0000000..1a41c03 --- /dev/null +++ b/usr/src/make_src/Make/lib/vroot/src/vroot.cc @@ -0,0 +1,344 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)vroot.cc 1.11 06/12/12 + */ + +#pragma ident "@(#)vroot.cc 1.11 06/12/12" + +#include <stdlib.h> +#include <string.h> + +#include <vroot/vroot.h> +#include <vroot/args.h> + +#include <string.h> +#include <sys/param.h> +#include <sys/file.h> + +#include <avo/intl.h> /* for NOCATGETS */ + +typedef struct { + short init; + pathpt vector; + char *env_var; +} vroot_patht; + +typedef struct { + vroot_patht vroot; + vroot_patht path; + char full_path[MAXPATHLEN+1]; + char *vroot_start; + char *path_start; + char *filename_start; + int scan_vroot_first; + int cpp_style_path; +} vroot_datat, *vroot_datapt; + +static vroot_datat vroot_data= { + { 0, NULL, NOCATGETS("VIRTUAL_ROOT")}, + { 0, NULL, NOCATGETS("PATH")}, + "", NULL, NULL, NULL, 0, 1}; + +void +add_dir_to_path(register char *path, register pathpt *pointer, register int position) +{ + register int size= 0; + register int length; + register char *name; + register pathcellpt p; + pathpt new_path; + + if (*pointer != NULL) { + for (p= &((*pointer)[0]); p->path != NULL; p++, size++); + if (position < 0) + position= size;} + else + if (position < 0) + position= 0; + if (position >= size) { + new_path= (pathpt)calloc((unsigned)(position+2), sizeof(pathcellt)); + if (*pointer != NULL) { + memcpy((char *)new_path,(char *)(*pointer), size*sizeof(pathcellt)); + free((char *)(*pointer));}; + *pointer= new_path;}; + length= strlen(path); + name= (char *)malloc((unsigned)(length+1)); + (void)strcpy(name, path); + if ((*pointer)[position].path != NULL) + free((*pointer)[position].path); + (*pointer)[position].path= name; + (*pointer)[position].length= length; +} + +pathpt +parse_path_string(register char *string, register int remove_slash) +{ + register char *p; + pathpt result= NULL; + + if (string != NULL) + for (; 1; string= p+1) { + if (p= strchr(string, ':')) *p= 0; + if ((remove_slash == 1) && !strcmp(string, "/")) + add_dir_to_path("", &result, -1); + else + add_dir_to_path(string, &result, -1); + if (p) *p= ':'; + else return(result);}; + return((pathpt)NULL); +} + +char * +get_vroot_name(void) +{ + return(vroot_data.vroot.env_var); +} + +char * +get_path_name(void) +{ + return(vroot_data.path.env_var); +} + +void +flush_path_cache(void) +{ + vroot_data.path.init= 0; +} + +void +flush_vroot_cache(void) +{ + vroot_data.vroot.init= 0; +} + +void +scan_path_first(void) +{ + vroot_data.scan_vroot_first= 0; +} + +void +scan_vroot_first(void) +{ + vroot_data.scan_vroot_first= 1; +} + +void +set_path_style(int style) +{ + vroot_data.cpp_style_path= style; +} + +char * +get_vroot_path(register char **vroot, register char **path, register char **filename) +{ + if (vroot != NULL) { + if ((*vroot= vroot_data.vroot_start) == NULL) + if ((*vroot= vroot_data.path_start) == NULL) + *vroot= vroot_data.filename_start;}; + if (path != NULL) { + if ((*path= vroot_data.path_start) == NULL) + *path= vroot_data.filename_start;}; + if (filename != NULL) + *filename= vroot_data.filename_start; + return(vroot_data.full_path); +} + +void +translate_with_thunk(register char *filename, int (*thunk) (char *), pathpt path_vector, pathpt vroot_vector, rwt rw) +{ + register pathcellt *vp; + pathcellt *pp; + register pathcellt *pp1; + register char *p; + int flags[256]; + +/* Setup path to use */ + if (rw == rw_write) + pp1= NULL; /* Do not use path when writing */ + else { + if (path_vector == VROOT_DEFAULT) { + if (!vroot_data.path.init) { + vroot_data.path.init= 1; + vroot_data.path.vector= parse_path_string(getenv(vroot_data.path.env_var), 0);}; + path_vector= vroot_data.path.vector;}; + pp1= path_vector == NULL ? NULL : &(path_vector)[0];}; + +/* Setup vroot to use */ + if (vroot_vector == VROOT_DEFAULT) { + if (!vroot_data.vroot.init) { + vroot_data.vroot.init= 1; + vroot_data.vroot.vector= parse_path_string(getenv(vroot_data.vroot.env_var), 1);}; + vroot_vector= vroot_data.vroot.vector;}; + vp= vroot_vector == NULL ? NULL : &(vroot_vector)[0]; + +/* Setup to remember pieces */ + vroot_data.vroot_start= NULL; + vroot_data.path_start= NULL; + vroot_data.filename_start= NULL; + + int flen = strlen(filename); + if(flen >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return; + } + + switch ((vp ?1:0) + (pp1 ? 2:0)) { + case 0: /* No path. No vroot. */ + use_name: + (void)strcpy(vroot_data.full_path, filename); + vroot_data.filename_start= vroot_data.full_path; + (void)(*thunk)(vroot_data.full_path); + return; + case 1: /* No path. Vroot */ + if (filename[0] != '/') goto use_name; + for (; vp->path != NULL; vp++) { + if((1 + flen + vp->length) >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + p= vroot_data.full_path; + (void)strcpy(vroot_data.vroot_start= p, vp->path); + p+= vp->length; + (void)strcpy(vroot_data.filename_start= p, filename); + if ((*thunk)(vroot_data.full_path)) return;}; + (void)strcpy(vroot_data.full_path, filename); + return; + case 2: /* Path. No vroot. */ + if (vroot_data.cpp_style_path) { + if (filename[0] == '/') goto use_name; + } else { + if (strchr(filename, '/') != NULL) goto use_name; + }; + for (; pp1->path != NULL; pp1++) { + p= vroot_data.full_path; + if((1 + flen + pp1->length) >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + if (vroot_data.cpp_style_path) { + (void)strcpy(vroot_data.path_start= p, pp1->path); + p+= pp1->length; + *p++= '/'; + } else { + if (pp1->length != 0) { + (void)strcpy(vroot_data.path_start= p, + pp1->path); + p+= pp1->length; + *p++= '/'; + }; + }; + (void)strcpy(vroot_data.filename_start= p, filename); + if ((*thunk)(vroot_data.full_path)) return;}; + (void)strcpy(vroot_data.full_path, filename); + return; + case 3: { /* Path. Vroot. */ + int *rel_path, path_len= 1; + if (vroot_data.scan_vroot_first == 0) { + for (pp= pp1; pp->path != NULL; pp++) path_len++; + rel_path= flags; + for (path_len-= 2; path_len >= 0; path_len--) rel_path[path_len]= 0; + for (; vp->path != NULL; vp++) + for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++) { + int len = 0; + if (rel_path[path_len] == 1) continue; + if (pp->path[0] != '/') rel_path[path_len]= 1; + p= vroot_data.full_path; + if ((filename[0] == '/') || (pp->path[0] == '/')) { + if(vp->length >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + (void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length; + len += vp->length; + }; + if (vroot_data.cpp_style_path) { + if (filename[0] != '/') { + if(1 + len + pp->length >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length; + *p++= '/'; + len += 1 + pp->length; + }; + } else { + if (strchr(filename, '/') == NULL) { + if (pp->length != 0) { + if(1 + len + pp->length >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + (void)strcpy(vroot_data.path_start= p, + pp->path); + p+= pp->length; + *p++= '/'; + len += 1 + pp->length; + } + } + }; + (void)strcpy(vroot_data.filename_start= p, filename); + if ((*thunk)(vroot_data.full_path)) return;};} + else { pathcellt *vp1= vp; + for (pp= pp1, path_len= 0; pp->path != NULL; pp++, path_len++) + for (vp= vp1; vp->path != NULL; vp++) { + int len = 0; + p= vroot_data.full_path; + if ((filename[0] == '/') || (pp->path[0] == '/')) { + if(vp->length >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + (void)strcpy(vroot_data.vroot_start= p, vp->path); p+= vp->length; + len += vp->length; + } + if (vroot_data.cpp_style_path) { + if (filename[0] != '/') { + if(1 + len + pp->length >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length; + *p++= '/'; + len += 1 + pp->length; + } + } else { + if (strchr(filename, '/') == NULL) { + if(1 + len + pp->length >= MAXPATHLEN) { + errno = ENAMETOOLONG; + continue; + } + (void)strcpy(vroot_data.path_start= p, pp->path); p+= pp->length; + *p++= '/'; + len += 1 + pp->length; + } + } + (void)strcpy(vroot_data.filename_start= p, filename); + if ((*thunk)(vroot_data.full_path)) return;};}; + (void)strcpy(vroot_data.full_path, filename); + return;};}; +} diff --git a/usr/src/make_src/Makefile b/usr/src/make_src/Makefile new file mode 100644 index 0000000..f12aeac --- /dev/null +++ b/usr/src/make_src/Makefile @@ -0,0 +1,38 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.65 06/12/12 +# + +TOP = . +include $(TOP)/rules/master.mk + +# Default build variables +CC=cc +CCC=CC +CC64=$(CC) +CCC64=$(CCC) + +SUBDIRS = Make + +include $(TOP)/rules/recurse.mk diff --git a/usr/src/make_src/exe/options.sh b/usr/src/make_src/exe/options.sh new file mode 100644 index 0000000..738e6c2 --- /dev/null +++ b/usr/src/make_src/exe/options.sh @@ -0,0 +1,105 @@ +#! /bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2003 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)options.sh 1.27 06/12/12 +# + +##----------------------------------------------------------------- +## Build options +## TeamWare can be built with different options: +## OPTION DEFAULT SWITCH +## -g debugging OFF debug-$variant.opt +## -g & -DDEBUG debugging OFF DEBUG-$variant.opt +## licensing enabled ON no_license.opt +## build source browser info OFF sb-$variant.opt +## usage tracking enabled OFF usage_tracking.opt +## +## Note that those with $variant in their names are variant-specific. +## +## To change the default value of any option, create a file in $(TOP) with the +## name of the switch. E.g., to create a workspace with debugging enabled, +## create the file +## $(TOP)/debug.opt +## before doing a make. The make need not be done for the entire workspace. +## +## Switches are set in places where they are needed. +## +## Note that the ability to disable licensing is commented out in the places +## where it is (currently, Jan 24 1996, used): lib/{cli,mgui}/src/Makefile +## so that we don't accidentally ship with licensing disabled. You also will have +## to manually make the switch in $(TOP)/exe executable. + + +echo '# This file is generated by $(TOP)/exe/options.sh' +echo "# *** DO NOT EDIT THIS FILE DIRECTLY ***" + +TOP=$1 +VARIANT=$2 + +echo " " +echo "# Debug options" +echo "#" +if [ -f $TOP/DEBUG-$VARIANT.opt ]; then + echo CFLAGS +=-g + echo CCFLAGS +=-g + echo CPPFLAGS += -DDEBUG + echo DEBUGLIB = -g + echo 'MOTIF_LD_RUN_PATH += -R$(CCR_ROOT_AUX)/$(VARIANT)/lib:$(CCR_ROOT)/$(VARIANT)/lib' +elif [ -f $TOP/debug-$VARIANT.opt ]; then + echo CFLAGS +=-g + echo CCFLAGS +=-g + echo DEBUGLIB = -g + echo 'MOTIF_LD_RUN_PATH += -R$(CCR_ROOT_AUX)/$(VARIANT)/lib:$(CCR_ROOT)/$(VARIANT)/lib' +else + echo CFLAGS +=-O + echo CCFLAGS +=-O + echo CPPFLAGS += -DNDEBUG + echo LDFLAGS += -norunpath -i -s + echo BDYNAMIC = -Bdynamic + echo BSTATIC = -Bstatic +fi + +if [ -f $TOP/no_license.opt ]; then + echo " " + echo "# Licensing options" + echo "#" + echo -DTW_LICENSE +fi + +if [ -f $TOP/sb-$VARIANT.opt ]; then + echo " " + echo "# Source Browser options" + echo "#" + echo CFLAGS += -sb + echo CCFLAGS += -sb +fi + +if [ -f $TOP/usage_tracking.opt ]; then + echo " " + echo "# Usage tracking options" + echo "#" + echo CPPFLAGS += -DUSAGE_TRACKING +fi + +echo CCFLAGS += -D_FILE_OFFSET_BITS=64 diff --git a/usr/src/make_src/exe/sanity-check.sh b/usr/src/make_src/exe/sanity-check.sh new file mode 100644 index 0000000..f59def8 --- /dev/null +++ b/usr/src/make_src/exe/sanity-check.sh @@ -0,0 +1,60 @@ +#! /bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)sanity-check.sh 1.6 06/12/12 +# + +# Run a sanity check on $1. Sanity is loosely defined as "ok to ship to a customer". +# Currently checks for the following: +# no forbidden RPATH +# no forbidden shared libraries +# Since sanity is only important for those things we ship to customers, don't +# check it on debugging builds. + +top=$1 +variant=`/bin/sh $top/exe/variant.sh` +if [ -f $top/debug-$variant.opt ]; then + exit 0 +fi + +prog=$2 +status=0 + +/usr/ccs/bin/dump -Lv $prog \ + | /bin/grep RPATH | \ + /bin/egrep 'net|export|set' > /dev/null +if [ $? -eq 0 ]; then + echo Error: $prog has forbidden RPATH + /usr/ccs/bin/dump -Lv $prog | /bin/grep RPATH + status=1 +fi + +/bin/ldd $prog |/bin/egrep 'libC|libsunmath|net|export|set' > /dev/null +if [ $? -eq 0 ]; then + echo Error: $prog has forbidden libraries + /bin/ldd $prog |/bin/egrep 'libC|libsunmath|net|export|set' + status=2 +fi + +exit $status diff --git a/usr/src/make_src/exe/variant.sh b/usr/src/make_src/exe/variant.sh new file mode 100644 index 0000000..d2fdaa1 --- /dev/null +++ b/usr/src/make_src/exe/variant.sh @@ -0,0 +1,55 @@ +#!/bin/sh +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)variant.sh 1.3 06/12/12 +# + + + +# Author: Achut Reddy +# Date: Fri Nov 4 12:00:24 PST 1994 + +# Handle HP-UX separately +sys=`uname -s` +case $sys in +HP-UX) + echo hp-ux + exit 0; + ;; +esac + +mach=`(mach || uname -p) 2> /dev/null` +case $mach in +i?86) + mach=intel ;; +esac + +rel=`uname -r` +case $rel in +5*) os=S2;; +4*) os=S1;; +*) os=UNKNOWN;; +esac + +echo ${mach}-${os} diff --git a/usr/src/make_src/include/Makefile b/usr/src/make_src/include/Makefile new file mode 100644 index 0000000..94af94e --- /dev/null +++ b/usr/src/make_src/include/Makefile @@ -0,0 +1,30 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)Makefile 1.4 06/12/12 +# + +TOP = ../.. +SUBDIRS = avo + +include $(TOP)/rules/recurse.mk diff --git a/usr/src/make_src/include/avo/avo_alloca.h b/usr/src/make_src/include/avo/avo_alloca.h new file mode 100644 index 0000000..3852f4c --- /dev/null +++ b/usr/src/make_src/include/avo/avo_alloca.h @@ -0,0 +1,49 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 1998 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)avo_alloca.h 1.4 06/12/12 + */ + +#pragma ident "@(#)avo_alloca.h 1.4 06/12/12" + +#ifndef _AVO_ALLOCA_H +#define _AVO_ALLOCA_H + +#include <alloca.h> + +#ifdef __SunOS_5_4 +// The following prototype declaration is necessary when compiling on Solaris +// 2.4 using 5.0 compilers. On Solaris 2.4 the necessary prototypes are not +// included in alloca.h. The 4.x compilers provide a workaround by declaring the +// prototype as a pre-defined type. The 5.0 compilers do not implement this workaround. +// This can be removed when support for 2.4 is dropped + +#include <stdlib.h> // for size_t +extern "C" void *__builtin_alloca(size_t); + +#endif // ifdef __SunOS_5_4 + +#endif // ifdef _AVO_ALLOCA_H + diff --git a/usr/src/make_src/include/avo/intl.h b/usr/src/make_src/include/avo/intl.h new file mode 100644 index 0000000..a689533 --- /dev/null +++ b/usr/src/make_src/include/avo/intl.h @@ -0,0 +1,77 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2001 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ +/* + * @(#)intl.h 1.19 06/12/12 + */ + +#pragma ident "@(#)intl.h 1.19 06/12/12" + +#ifndef _AVO_INTL_H +#define _AVO_INTL_H + +#if defined(SUN4_x) || defined(HP_UX) +#include <avo/widefake.h> +#endif + +/* + * For catgets + */ +#include <nl_types.h> + +#ifdef HP_UX +#ifdef __cplusplus +#ifndef _STDLIB_INCLUDED +#include <stdlib.h> /* for wchar_t definition and HP-UX - */ +#endif /* wide character function prototypes. */ +extern "C" { +char *gettext(char *msg); +char *dgettext(const char *, const char *); +char *bindtextdomain(const char *, const char *); +char *textdomain(char *); +} +#endif /* __cplusplus */ +#endif + +/* + * NOCATGETS is a dummy macro that returns it argument. + * It is used to identify strings that we consciously do not + * want to apply catgets() to. We have tools that check the + * sources for strings that are not catgets'd and the tools + * ignore strings that are NOCATGETS'd. + */ +#define NOCATGETS(str) (str) + +/* + * Define the various text domains + */ +#define AVO_DOMAIN_CODEMGR "codemgr" +#define AVO_DOMAIN_VERTOOL "vertool" +#define AVO_DOMAIN_FILEMERGE "filemerge" +#define AVO_DOMAIN_DMAKE "dmake" +#define AVO_DOMAIN_PMAKE "pmake" +#define AVO_DOMAIN_FREEZEPOINT "freezept" +#define AVO_DOMAIN_MAKETOOL "maketool" + +#endif diff --git a/usr/src/make_src/rules/computed-options.mk b/usr/src/make_src/rules/computed-options.mk new file mode 100644 index 0000000..3c7d1ba --- /dev/null +++ b/usr/src/make_src/rules/computed-options.mk @@ -0,0 +1,37 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)computed-options.mk 1.3 06/12/12 +# + +# +# Including this file causes re-computation of the options used during a build +# + +$(TOP)/rules/options-$(VARIANT).mk: $(TOP)/exe/options.sh FORCE + /bin/rm -f $(TOP)/rules/options-$(VARIANT).mk + /bin/sh $(TOP)/exe/options.sh $(TOP) $(VARIANT) > $(TOP)/rules/options-$(VARIANT).mk + +FORCE: + +include $(TOP)/rules/options-$(VARIANT).mk diff --git a/usr/src/make_src/rules/derived.mk b/usr/src/make_src/rules/derived.mk new file mode 100644 index 0000000..89fd719 --- /dev/null +++ b/usr/src/make_src/rules/derived.mk @@ -0,0 +1,66 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)derived.mk 1.15 06/12/12 +# + +# Include this makefile in directories which contain source whose derived +# files are to be built in ../<variant>. + +# The source directory must contain a makefile with these contents: +# +# TOP = <as appropriate> +# include $(TOP)/rules/master.mk +# SRC = <as appripriate> +# include $(TOP)/rules/variant.mk +# +# The source directory must also contain a makefile named "Derived.mk" +# which is used to build the derived files. +# +# TOP is defined as a relative path to the root of the workspace +# SRC is defined as a relative path from the derived files' directory to the +# source files' directory, and is typically ../src. + +include $(TOP)/rules/$(VARIANT).mk + +all := TARG = all +install := TARG = install +clean := TARG = clean +test := TARG = test +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +all install clean test l10n_install i18n_install: $(VARIANT) $(V9_VARIANT) + +SRC = ../src +MFLAGS += SRC=$(SRC) + +# Conditional is in place so a "make" from the top level will work on partial +# source heirarchies. +$(VARIANT) $(V9_VARIANT): FRC + if [ ! -d $@ ]; then \ + mkdir $@ ; \ + fi + cd $@; $(MAKE) $(MFLAGS) -f $(SRC)/Variant.mk RELEASE_VER="$(RELEASE_VER)" DESTDIR=$(DESTDIR) V9FLAGS="$(V9FLAGS)" VAR_DIR=$(VAR_DIR) CC=$(CC) CCC=$(CCC) $(TARG); + +FRC: diff --git a/usr/src/make_src/rules/dmake.mk b/usr/src/make_src/rules/dmake.mk new file mode 100644 index 0000000..7ca8548 --- /dev/null +++ b/usr/src/make_src/rules/dmake.mk @@ -0,0 +1,33 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)dmake.mk 1.8 06/12/12 +# + +AVO_DM_LIBS = $(LIBDM) +AVO_DMCONF_LIBS = $(LIBDMCONF) +AVO_DMRC_LIBS = $(LIBDMRC) +AVO_DMTHREAD_LIBS = $(LIBDMTHREAD) +AVO_PUBDMSI18N_LIBS = $(LIBPUBDMSI18N) +AVO_RX_LIBS = $(LIBRX) + diff --git a/usr/src/make_src/rules/i18n-install.mk b/usr/src/make_src/rules/i18n-install.mk new file mode 100644 index 0000000..06e90fb --- /dev/null +++ b/usr/src/make_src/rules/i18n-install.mk @@ -0,0 +1,73 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1997 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)i18n-install.mk 1.23 06/12/12 +# + +include $(TOP)/rules/master.mk + +# +# Included Makefile that installs i18n message catalogs. +# +# Before including this Makefile the following variables should be set: +# PACKAGE name of the package being installed +# replaced by PRODVER in order to install multiple pkgs in +# a single path. --emk 2/96 +# +# TEXTDOMAIN name of default textdomain used by gettext() calls +# APPPATH location to find the msg file +# + +PRODVER = usr + +LIB_DESTDIR = $(DESTDIR)/$(PRODVER)/lib +CAT_DESTDIR = $(LIB_DESTDIR)/locale/C/LC_MESSAGES +HELP_DIR = help +HELP_SYML_INST_DIR = $(LIB_DESTDIR) +HELP_SYML_PTS_TO_DIR = ./locale/C +LANG_DIR = $(LIB_DESTDIR)/local/C + +#i18n_install: $(CAT_DESTDIR) .WAIT msg_catalogs help_symlink +i18n_install: +i18n_gui_install: $(CAT_DESTDIR) .WAIT gui_msg_catalogs help_symlink + +$(CAT_DESTDIR): + $(INSTALL) -d $@ + +# +# Find the message catalog in the $VAriant dir +# install the files into the package's destination. +# + +msg_catalogs: FRC + cp $(APPPATH)/$(TEXTDOMAIN).msg $(CAT_DESTDIR) + +gui_msg_catalogs: FRC + cp $(APPPATH)/$(TEXTDOMAIN).po $(CAT_DESTDIR) + +help_symlink: FRC +# @ if [! -d $(LANG_DIR)/$(HELP_DIR) ]; then \ +# cd $(LANG_DIR); ln -s LC_MESSAGES $(HELP_DIR) \ +# fi \ + +FRC: diff --git a/usr/src/make_src/rules/import.mk b/usr/src/make_src/rules/import.mk new file mode 100644 index 0000000..6c3a6de --- /dev/null +++ b/usr/src/make_src/rules/import.mk @@ -0,0 +1,28 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)import.mk 1.25 06/12/12 +# +# @(#)import.mk 1.8 96/04/16 SMI + +VIDEO_VER = 1.0 diff --git a/usr/src/make_src/rules/install.mk b/usr/src/make_src/rules/install.mk new file mode 100644 index 0000000..aa28359 --- /dev/null +++ b/usr/src/make_src/rules/install.mk @@ -0,0 +1,240 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1998 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)install.mk 1.53 06/12/12 +# + +# +# This is an included Makefile that contains the standard +# install lines for a program. +# +# INCLUDE THIS ONLY AFTER INCLUDING $(TOP)/rules/master.mk +# +# Before including this Makefile the following variables should be set: +# PROG the name of the program +# PROG_DIR bin || etc, lowest level directory for executables +# LIB_DIR usually just lib; destination for libraries, +# non-localized bitmaps, etc. +# LICENSE_DIR_SRC where LICENSE_DIR will link to +# DESTDIR destination directory for the install +# PACKAGE name of the package containing the program +# +# PACKAGE is now being overridden by PRODVER for installation +# purposes since multiple packages are being installed +# into a single install path below PRODVER 2/96 --emk +# +# HELP_INFO optionally set to a list of .info files to install +# HELP_INFO is initially set in gui.Makefile +# RES_FILE optionally set name by which resource file is +# known to the app itself (e.g. XCodeManager). +# CDE_RES_FILE optionally set name of resource file for CDE guis +# (e.g. XCodeManager.cde). +# NCDE_RES_FILE optionally set name of resource file for motif guis +# PWI_FILE optionally set name of PWI configuration file for guis +# Installed in RES_DIR +# +# This install technique uses make's dependencies to decide whether +# or not to install something. If the installed file is more recent +# than the one in the source heirarchy, then no install will occur. +# +# The INST_PROG definition makes this install rule work for makefiles +# that build more than one program, e.g. several scripts that share +# the same source directory. To work, this install.Makefile must be +# included after the "all" target has been defined but before the +# rules used to build the programs to be installed. (see trans/scripts) +# +# For makefiles that build only one program, this install.Makefile can +# be included at the end, after the rules used to build the program. +# (see bin.cc.Makefile). + +# +# The references to PROG_DIR below must be $$ references because +# PROG_DIR is conditionally set in the CodeManager/etc/diff3_merge +# Makefile. But, if it is conditional, the implicit target for +# $(DESTDIR)/$(PROG_DIR) doesn't work. Make returns that it doesn't +# know how to build that target. +# +# I made changes to add PROG_DIR=<value> in all the makefiles which include +# install.mk. This is needed because of the assignment to +# PGK_DIR_PROG_DIR. SYML_DIR is still conditional and set according to +# to which target is being built. it would be nice to set PROG_DIR by +# default, but to do this, the reference in the PKG_DIR_PROG_DIR assignment +# must be re-done... LK +# + +PKG_DIR = $(DESTDIR)/$(PRODVER) +LOCALE_PATH = lib/locale/C +HELP_DIR = $(PKG_DIR)/$(LOCALE_PATH)/LC_MESSAGES +PWI_PATH = $(LOCALE_PATH)/pwi_config +PWI_DIR = $(PKG_DIR)/$(PWI_PATH) +LICENSE_DIR = $(DESTDIR)/license_dir +PKG_DIR_PROG_DIR = $(DESTDIR)/$(PRODVER)/$(PROG_DIR) +PKG_DIR_LIB_DIR = $(DESTDIR)/$(PRODVER)/$(LIB_DIR) +CDE_RES_DIR = $(DESTDIR)/$(PRODVER)/$(LOCALE_PATH)/app-defaults/CDE +NCDE_RES_DIR = $(DESTDIR)/$(PRODVER)/$(LOCALE_PATH)/app-defaults/non-CDE +INST_PROG = $(PROG:%=$(PKG_DIR_PROG_DIR)/%) +INST_LIB = $(LIBSS:%=$(PKG_DIR_LIB_DIR)/%) +# +# INST_HELP is the list of .info files to be installed +# +INST_HELP = $(HELP_INFO:%=$(HELP_DIR)/%) + +# +INST_SYMLINK = /bin/csh $(TOOLS_PATH)/inst_symlink + +# INSTALLING PERSISTENT PROCESSES: +# +# If the macro INST_PERSIST is set to TRUE, move a copy of $(PROG) out of +# the way into a unique name so it doesn't clobber the last version moved. +# +# A way to make this conditional in the individual Makefiles is to include +# something like this in the Makefile which needs to install a persistent +# process: +# +# INST_PERSIST = $(SWTEAM_PERSIST) +# +# Where SWTEAM_PERSIST is set in your .cshrc or .login to TRUE. This allows +# it to be turned off and on on a global scale, and still only apply to those +# executables which have INST_PERSIST set in their Makefiles. +# + +#install:: \ +# $(PKG_DIR_PROG_DIR) \ +# .WAIT \ +# $(PKG_DIR_LIB_DIR) \ +# .WAIT \ +# $(HELP_DIR) \ +# .WAIT \ +# $(PWI_DIR) \ +# .WAIT \ +# $(PWI_DIR)/$(PWI_FILE) \ +# .WAIT \ +# symlinks \ +# $(LICENSE_DIR) \ +# $(CDE_RES_DIR) \ +# $(NCDE_RES_DIR) \ +# .WAIT \ +# $(INST_PROG) \ +# $(INST_LIB) \ +# $(INST_HELP) \ +# $$(INST_ABOX_ABOX) \ +# $$(INST_ABOX_ADDR) \ +# $(CDE_RES_DIR)/$(RES_FILE) \ +# $(NCDE_RES_DIR)/$(RES_FILE) \ +# .WAIT \ +# post-install + +# +# Empty rule here; packages can add their own functionality. +# +post-install:: FRC + +# +# Number of earlier versions to save. +# +SAVE_NUM = 1 + +$(PKG_DIR_PROG_DIR)/%: % + @if [ "$(INST_PERSIST)" = "TRUE" -a -f $@ ]; then \ + while [ `ls $@.* | wc -l` -gt $(SAVE_NUM) ]; do \ + echo "rm -f `ls $@.* | head -1`";\ + rm -f `ls $@.* | head -1`;\ + done; \ + echo "mv -f $@ $@.`date +%m.%d.%H.%M`"; \ + mv -f $@ $@.`date +%m.%d.%H.%M`; \ + fi + echo "$(INSTALL) $< $@" + $(INSTALL) $< $@ + + +# +# Don't put the dependency upon $(PKG_DIR_PROG_DIR) on the +# $(PKG_DIR_PROG_DIR)/% target line because it causes the executables to be +# installed twice regardless of their relation to the current executable +# +$(PKG_DIR_PROG_DIR): + @if [ ! -d $@ ]; then \ + $(INSTALL) -d $@; \ + fi; \ + +$(PKG_DIR_LIB_DIR): + @if [ ! -d $@ ]; then \ + $(INSTALL) -d $@; \ + fi; \ + +# +# Install the help files listed in $(INST_HELP). Each of the files +# listed in $(INST_HELP) lives in directory $(HELP_DIR). +# +# Needs to be able to support HELP_INFO with values in current directory +# as well as info files from other directories. +# +$(HELP_DIR)/%.info: %.info + $(INSTALL) $< $@ + +$(HELP_DIR)/%.info: $(TOP)/libgui/%.info + $(INSTALL) $< $(HELP_DIR)/$(@F) + +$(HELP_DIR): + @if [ ! -d $(HELP_DIR) ]; then \ + $(INSTALL) -d $@; \ + fi + +$(PWI_DIR): + @if [ ! -d $(PWI_DIR) ]; then \ + $(INSTALL) -d $@; \ + fi + +# +# hack in license_dir link -- probably outta be in symlinks section +# +$(LICENSE_DIR): + echo "$(INST_SYMLINK) $(LICENSE_DIR_SRC) $(DESTDIR) license_dir" + $(INST_SYMLINK) $(LICENSE_DIR_SRC) $(DESTDIR) license_dir + +$(PWI_DIR)/$(PWI_FILE): $(SRC)/$(PWI_FILE) + @if [ "$(PWI_FILE)" != "" ]; then \ + $(INSTALL) -m 0444 $(SRC)/$(PWI_FILE) $@; \ + fi + +$(CDE_RES_DIR)/$(RES_FILE): $(CDE_RES_FILE) + @if [ "$(CDE_RES_FILE)" != "" ]; then \ + $(INSTALL) -m0444 $(CDE_RES_FILE) $(CDE_RES_DIR)/$(RES_FILE); \ + fi + +$(NCDE_RES_DIR)/$(RES_FILE): $(NCDE_RES_FILE) + @if [ "$(NCDE_RES_FILE)" != "" ]; then \ + $(INSTALL) -m0444 $(NCDE_RES_FILE) $(NCDE_RES_DIR)/$(RES_FILE); \ + fi + +$(CDE_RES_DIR): + @if [ "$(CDE_RES_FILE)" != "" ]; then \ + $(INSTALL) -d $@; \ + fi + +$(NCDE_RES_DIR): + @if [ "$(NCDE_RES_FILE)" != "" ]; then \ + $(INSTALL) -d $@; \ + fi + +FRC: diff --git a/usr/src/make_src/rules/intel-S2.mk b/usr/src/make_src/rules/intel-S2.mk new file mode 100644 index 0000000..daa77cc --- /dev/null +++ b/usr/src/make_src/rules/intel-S2.mk @@ -0,0 +1,60 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2004 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)intel-S2.mk 1.16 06/12/12 +# + +include $(TOP)/rules/solaris.mk + +# Please keep each list alphabetically sorted. + +# +# Make variables +# + +# +# Paths +# +TOOLS_PATH = $(TOP)/exe + +# +# Programs +# + +# +# Flags +# +CPPFLAGS += -DSUN5_0 -DSYSV -Dx86 + +# +# amd64-S2 Flags +# +amd64-S2 := V9FLAGS = -O -xarch=amd64 +amd64-S2 := VAR_DIR = /amd64 + +# +# This is temporary until both 32- and 64-bit stuff are to be compiled +# with the same compiler. +# +amd64-S2 := CC = $(CC64) +amd64-S2 := CCC = $(CCC64) diff --git a/usr/src/make_src/rules/l10n-install.mk b/usr/src/make_src/rules/l10n-install.mk new file mode 100644 index 0000000..9050cf2 --- /dev/null +++ b/usr/src/make_src/rules/l10n-install.mk @@ -0,0 +1,70 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1998 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)l10n-install.mk 1.7 06/12/12 +# + +# READ-THIS-PART: +# Since L10N_SRCS are derived sources files, the make target +# "make_l10n_install" script MUST be executed after a +# complete build of the integration workspace. The make_l10n_install +# scripts resides in the TOOLS_PATH directory. +# + +L10N_SCRIPT = /bin/csh $(TOOLS_PATH)/inst_l10n + + +# Before including this Makefile the following variables should be set: +# +# +# DESTDIR the destination workspace where the L10N_SRCS will +# be installed. +# SOURCE_WS the source workspace from which the files will be +# installed. +# L10N_SRCS sources that need to be installed in the above +# DESTDIR. +# L10N_SCRIPT the script that will install the files under +# sccs control in the destination directory +# workspace. +# TOOLS_PATH location for the L10N_SCRIPT +# +# + +ALL_USAGE = "Usage: make DESTDIR=<value> SOURCE_WS=<value> l10n_install" +CWD:sh = pwd + +l10n_install:: l10n_install_usage FRC + @$(L10N_SCRIPT) $(DESTDIR) $(SOURCE_WS) $(CWD) \ + $(L10N_SRCS) +FRC: + +l10n_install_usage: FRC + @if [ "$(DESTDIR)" = "" -o "$(SOURCE_WS)" = "" ]; then \ + echo $(ALL_USAGE); \ + exit 1; \ + fi; + @if [ "$(CWD)" = "" ]; then \ + echo $(ALL_USAGE); \ + exit 1; \ + fi +FRC: diff --git a/usr/src/make_src/rules/lib.mk b/usr/src/make_src/rules/lib.mk new file mode 100644 index 0000000..f38f9aa --- /dev/null +++ b/usr/src/make_src/rules/lib.mk @@ -0,0 +1,131 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)lib.mk 1.33 06/12/12 +# + +# +# This Makefile contains common rules for building libraries. +# It expects the following variables to be defined: +# +# LIBNAME the name of the library being built +# CCSRCS C++ source files +# CSRCS C source files +# BIGCSRCS C++ source files with .C suffix (so checkgettext isn't run) +# + +CCOBJS = $(CCSRCS:%.cc=%.o) +COBJS = $(CSRCS:%.c=%.o) +BIGCOBJS = $(BIGCSRCS:%.C=%.o) + +OBJS += $(CCOBJS) $(COBJS) $(BIGCOBJS) + +L10N_SRCS = $(LIBNAME)_srrcat.po messages.po + +# +# Is this '[d]make' connected to a terminal? +# +TTY :sh= if test -t 2; then echo true; else echo false; fi + +# +# This complicated set of commands determine if there are +# any .o files in the library that no longer belong there. +# If so, the library must be removed and rebuilt from scratch. +# If the old .o files are left in the library, then a program that +# references a routine in one of these .o files will still build +# until the library gets completely rebuilt, in which case it will +# no longer build. +# In addition, because $? macro is used in the command that builds +# this library, command dependency checking is disabled. Even if +# this command changes, the library won't be rebuilt. The library's +# list of dependencies appear in a separate command, which is subject +# to command dependency checking (echo to /dev/null), to ensure that +# the library rebuilt when its list of dependencies change. +# + +# XD_INCLS is defined in rules/motif-lib.mk and will +# be empty if not called from motif-lib.mk + +$(LIBNAME): $(OBJS) + @echo "Building $(LIBNAME)" > \ + `$(TTY) && test -t 0 && tty || echo /dev/null` + @echo $(OBJS) > /dev/null + @?ar t $(LIBNAME) | sed -e /__.SYMDEF/d | sort > ar.t.$$$$; \ + for i in $(OBJS); do \ + echo $$i; \ + done | sort | comm -23 ar.t.$$$$ - > extras.$$$$; \ + if [ -s extras.$$$$ ]; then \ + echo rm -f $(LIBNAME); \ + rm -f $(LIBNAME); \ + echo ar rv $(LIBNAME) $(OBJS); \ + ar rv $(LIBNAME) $(OBJS); \ + else \ + echo ar crv $(LIBNAME) $?; \ + ar crv $(LIBNAME) $?; \ + fi; \ + rm -f ar.t.$$$$ extras.$$$$ + @if [ -f $(RANLIB) ]; then \ + echo $(RANLIB) $(LIBNAME); \ + $(RANLIB) $(LIBNAME); \ + fi + +#all install:: $(LIBNAME) catalogs +###all install:: $(LIBNAME) +all: $(LIBNAME) + +install: $(LIBNAME) + +#all:: $(LIBNAME) +# +#install:: all catalogs + +clean:: + $(RM) $(OBJS) $(LIBNAME) $(CLEANFILES) $(CATALOG) + +# temporarily install catalogs here - will move to l10n-install later +# when mesg files are versioned +LIB_DESTDIR = $(DESTDIR)/$(PRODVER)/lib +CAT_DESTDIR = $(LIB_DESTDIR)/locale/C/LC_MESSAGES + +#also temporary, until I find a variant specific place to find this tool +COMPMSG = + +catalogs:: + $(GENMSG) -l $(SRC)/genmsg.project -o $(MSG_FILE) `find $(I18N_DIRS) \( -name '*.cc' -o -name '*.c' -o -name '*.y' -o -name '*.h' \) -print | grep -v /SCCS/` + rm -f *.cc.new +# @ if [ -f $(SRC)/$(MSG_FILE) ]; then \ +# echo "running compmsg on $(MSG_FILE)"; \ +# $(COMPMSG) -n $(SRC)/$(MSG_FILE) $(MSG_FILE); \ +# fi + + +# @ if [ ! -d $(CAT_DESTDIR) ]; then \ +# $(INSTALL) -d $@ \ +# fi +# cp $(MSG_FILE) $(CAT_DESTDIR) + +FRC: + +include $(TOP)/rules/l10n-install.mk + +include $(TOP)/rules/computed-options.mk diff --git a/usr/src/make_src/rules/libraries.mk b/usr/src/make_src/rules/libraries.mk new file mode 100644 index 0000000..b2d4c46 --- /dev/null +++ b/usr/src/make_src/rules/libraries.mk @@ -0,0 +1,62 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)libraries.mk 1.9 06/12/12 +# + +# This file defines make variables for libraries libraries which +# are provided in both debuggable (-g) and optimized (-O) forms. +# +# See $(TOP)/exe/build-debuglib, rules/{singleton, motif-app}.mk, + +# Please keep both of the following lists alphabetized. + +# These libraries exist in both -g and non-g forms. +# +LIBDM = -ldm$(DEBUGLIB) +LIBDMCONF = -ldmconf$(DEBUGLIB) +LIBDMRC = -ldmrc$(DEBUGLIB) +LIBDMTHREAD = -ldmthread$(DEBUGLIB) +LIBLICMOTIF = -llicmotif$(DEBUGLIB) +LIBLICTXT = -llictxt$(DEBUGLIB) +LIBMGUI = -lmgui$(DEBUGLIB) +LIBPSDEFS = -lpsdefs$(DEBUGLIB) +LIBPSWIDGETS = -lPsWidgets$(DEBUGLIB) +LIBPSUTILS = -lPsUtils$(DEBUGLIB) +LIBPUBDMSI18N = -lpubdmsi18n$(DEBUGLIB) +LIBPWICLIENT = -lpwiclient$(DEBUGLIB) +LIBPWITOOLBOX = -lpwitoolbox$(DEBUGLIB) +LIBRX = -lrx$(DEBUGLIB) +LIBUTIL = -lutil$(DEBUGLIB) +LIBXDCLASS = -lxdclass$(DEBUGLIB) + +# These libraries exist only in non-g form. That does *not* mean that they are +# not *compiled* without -g., only that they don't exist in a libXXX-g.a form. +# +LIBLOG = -llog +LIBMSSPKG = -lmsspkg +LIBPATHUTILS = -lpathutils +LIBPSCCHART = -lpscchart +LIBPSCHART = -lpschart +LIBTIMELINE = -ltimeline +LIBXPM = $(BSTATIC) -lXpm $(BDYNAMIC) diff --git a/usr/src/make_src/rules/master.mk b/usr/src/make_src/rules/master.mk new file mode 100644 index 0000000..eae7f19 --- /dev/null +++ b/usr/src/make_src/rules/master.mk @@ -0,0 +1,109 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)master.mk 1.142 06/12/12 +# + +include $(TOP)/rules/variant.mk + +.KEEP_STATE_FILE: .make.state_${VARIANT} + +include $(TOP)/rules/$(VARIANT).mk +#include $(TOP)/lib/Lib.mk + +#include $(TOP)/rules/libraries.mk + +DESTDIR = + +# +# Default target to build if no target is specified. +# All Makefiles should either define an "all" target, or set +# DEFAULT_TARGET to the default target +# +DEFAULT_TARGET = all +default_target: $$(DEFAULT_TARGET) + +#Tools needed for i18n +GENMSG = genmsg + +##----------------------------------------------------------------- + +CHMOD = /bin/chmod +LEX = /usr/ccs/bin/lex +MV = /bin/mv +RANLIB = /bin/ranlib +YACC = /usr/ccs/bin/yacc + +##----------------------------------------------------------------- + +CPPFLAGS += -DINTER \ + -I$(TOP)/include + +LINTFLAGS += -buxz + + +#LIB += $(LIBCMM) $(LIBSCCS) $(LIBUTIL) -lw + +##----------------------------------------------------------------- +## Rules for building derived files from $(SRC) +## +## Run check_catgets before compiling to see if there are any strings that need +## i18n attention. +## +## Use .C extension for derrived source files (e.g., yacc output) and on any +## others on which you don't want to first run check_catgets. + +%.o: $(SRC)/%.cc + $(COMPILE.cc) $(OUTPUT_OPTION) $< + +%.o:$(SRC)/%.C + $(COMPILE.cc) $(OUTPUT_OPTION) $< + +%.o:$(SRC)/%.c + $(COMPILE.c) $(OUTPUT_OPTION) $< + +### Generate preprocessor output +CPP.c = $(CC) $(CFLAGS) $(CINCLS) -E +CPP.cc = $(CCC) $(CCFLAGS) $(CCINCLS) -E + +%.E: $(SRC)/%.cc + $(CPP.cc) $(CPPFLAGS) $(SRC)/$(@:%.E=%.cc) > $*.E + +%.E:$(SRC)/%.C + $(CPP.cc) $(CPPFLAGS) $(SRC)/$(@:%.E=%.C) > $*.E + +%.E:$(SRC)/%.c + $(CPP.c) $(CPPFLAGS) $(SRC)/$(@:%.E=%.c) > $*.E + +### Lex and yacc +%.cc: $(SRC)/%.y + $(RM) $*.cc $*.h + $(YACC) $(YFLAGS) $(SRC)/$*.y + $(MV) y.tab.c $*.cc + $(MV) y.tab.h $*.h + $(CHMOD) a-w $*.cc $*.h + +%.C: $(SRC)/%.l + $(RM) $*.C + $(LEX) $(LEXOPT) $(SRC)/$*.l > $*.C + $(CHMOD) a-w $@ diff --git a/usr/src/make_src/rules/recurse.mk b/usr/src/make_src/rules/recurse.mk new file mode 100644 index 0000000..d0963ad --- /dev/null +++ b/usr/src/make_src/rules/recurse.mk @@ -0,0 +1,58 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2002 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)recurse.mk 1.15 06/12/12 +# + +# Include this Makefile in directories which simply cd down a level +# and continue the build. +# +# The SUBDIRS macro must be set before including recurse.Makefile +# The OTHER_TARGS macro can be set to process targets other than +# directories. + +all := TARG = all +install := TARG = install +clean := TARG = clean +l10n_install := TARG = l10n_install +i18n_install := TARG = i18n_install + +# Are we _really_ using OTHER_TARGS??? +#all install clean l10n_install: $(SUBDIRS) $(OTHER_TARGS) +all install clean l10n_install i18n_install:: $(SUBDIRS) $(OTHER_TARGS) + +# Conditional is in place so a "make" from the top level will work on partial +# source heirarchies. +# +# "MAKEFILE" can be set by makes driving this one to cause a particular +# makefile to be used. E.g., MAKEFILE=-f foo.mk +# +$(SUBDIRS): FRC + @if [ -d $@ ]; then \ + echo "cd $@; $(MAKE) $(MAKEFILE) $(MFLAGS) CC=$(CC) CCC=$(CCC) DESTDIR=$(DESTDIR) $(TARG)"; \ + cd $@; $(MAKE) $(MAKEFILE) $(MFLAGS) CC=$(CC) CCC=$(CCC) DESTDIR=$(DESTDIR) $(TARG); \ + fi + +FRC: + + diff --git a/usr/src/make_src/rules/singleton.mk b/usr/src/make_src/rules/singleton.mk new file mode 100644 index 0000000..3dda8b6 --- /dev/null +++ b/usr/src/make_src/rules/singleton.mk @@ -0,0 +1,63 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)singleton.mk 1.64 06/12/12 +# + +# This is an included Makefile for a program that consists of a single C++ +# source file and is built with the standard Avocet library. + +# Before including this Makefile the following variables should be set: +# TOP the path from the including Makefile to this one +# PROG the name of the program +# DESTDIR destination directory for the install +# +# All other information is derived from PROG. + +SRCS = $(PROG).cc $(MORE_SRC) +OBJS = $(SRCS:%.cc=%.o) + +LIB += $(LIBCLI) $(LIBLICTXT) -lintl -lm + +##----------------------------------------------------------------- + +all install:: $(PROG) + +include $(TOP)/rules/verstring.mk + +$(PROG): $(OBJS) + @echo "#pragma ident \"@(#)$(VERSTRING1)\"" > timestamp.c + @echo $(VERSTRING2) >> timestamp.c + cc -w -c timestamp.c + $(CCC) $(CCFLAGS) $(LDFLAGS) timestamp.o -o $@ \ + $(OBJS) $(LIB) $(I18LIB) $(LDLIB) + /bin/sh $(TOP)/exe/sanity-check.sh $(TOP) $(PROG) + +clean: + $(RM) $(OBJS) $(PROG) + +PROG_DIR = bin + +include $(TOP)/rules/install.mk + +include $(TOP)/rules/computed-options.mk diff --git a/usr/src/make_src/rules/solaris.mk b/usr/src/make_src/rules/solaris.mk new file mode 100644 index 0000000..d5ef1a4 --- /dev/null +++ b/usr/src/make_src/rules/solaris.mk @@ -0,0 +1,55 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2006 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)solaris.mk 1.19 06/12/12 +# + +# Please keep each list alphabetically sorted. + +# +# Make variables +# +OPENWINHOME = /usr/openwin + +# +# Paths +# +#LD_LIBRARY_PATH = /usr/dt/lib:$(OPENWINHOME)/lib +# +SWHOME = + +# +# Programs +# +#CC = cc +INSTALL = /usr/ucb/install +RPCGEN = /usr/5bin/rpcgen + +# +# Flags +# +CPPFLAGS += -compat=4 +I18LIB = -lintl +LDFLAGS += -compat=4 -staticlib=libC +LEXOPT = -tw +MOTIF_LD_RUN_PATH = /usr/dt/lib:/usr/openwin/lib diff --git a/usr/src/make_src/rules/sparc-S2.mk b/usr/src/make_src/rules/sparc-S2.mk new file mode 100644 index 0000000..d1fb437 --- /dev/null +++ b/usr/src/make_src/rules/sparc-S2.mk @@ -0,0 +1,61 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1998 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)sparc-S2.mk 1.13 06/12/12 +# + +include $(TOP)/rules/solaris.mk + +# Please keep each list alphabetically sorted. + +# +# Make variables +# + +# +# Paths +# +TOOLS_PATH = $(TOP)/exe + +# +# Programs +# + +# +# Flags +# +CPPFLAGS += -DSUN5_0 -DSYSV + +# +# v9 Flags +# +sparcv9 := V9FLAGS = -xarch=v9 +sparcv9 := VAR_DIR = /sparcv9 + +# +# This is temporary until both 32- and 64-bit stuff are to be compiled +# with the same compiler. Currently 32-bit should use 4.2 compiler +# but 64-bit should use 5.0 compiler. +# +sparcv9 := CC = $(CC64) +sparcv9 := CCC = $(CCC64) diff --git a/usr/src/make_src/rules/variant.mk b/usr/src/make_src/rules/variant.mk new file mode 100644 index 0000000..d5fa217 --- /dev/null +++ b/usr/src/make_src/rules/variant.mk @@ -0,0 +1,45 @@ +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or http://www.opensolaris.org/os/licensing. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 1996 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# +# @(#)variant.mk 1.2 06/12/12 +# +VARIANT:sh=if [ `uname -r | cut -d . -f1` = 4 ] ; \ +then echo sparc-S1 ; \ +elif [ `uname -s` = HP-UX ] ; \ +then echo hp-ux ; \ +else if [ `uname -p` = sparc ] ; \ + then \ + echo sparc-S2 ; \ + elif [ `uname -p` = i386 ] ; \ + then \ + echo intel-S2 ; \ + elif [ `uname -p` = ppc ] ; \ + then \ + echo ppc-S2 ; \ + else \ + echo "UNKNOWN OS" ; \ + exit 1 ; \ + fi ; \ +fi + + |