summaryrefslogtreecommitdiff
path: root/usr/src/lib/libpp
diff options
context:
space:
mode:
authorchin <none@none>2007-08-17 12:01:52 -0700
committerchin <none@none>2007-08-17 12:01:52 -0700
commitda2e3ebdc1edfbc5028edf1354e7dd2fa69a7968 (patch)
tree5280d3b78e289fe9551371ab6e7f15ef9944ea14 /usr/src/lib/libpp
parent073dbf9103ef2a2b05d8a16e2d26db04e0374b0e (diff)
downloadillumos-joyent-da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968.tar.gz
6437624 RFE: Add ksh93 (as /usr/bin/ksh93) and libshell.so to OS/Net
6505835 AST tools and library (libpp) required for creating l10n messages for ksh93 PSARC/2006/550 Korn Shell 93 Integration PSARC/2006/587 /etc/ksh.kshrc for ksh93 PSARC/2007/035 ksh93 Amendments Contributed by Roland Mainz <roland.mainz@nrubsig.org> --HG-- rename : usr/src/lib/libcmd/common/mapfile-vers => deleted_files/usr/src/lib/libcmd/common/mapfile-vers rename : usr/src/lib/libcmd/common/placeholder.c => deleted_files/usr/src/lib/libcmd/common/placeholder.c
Diffstat (limited to 'usr/src/lib/libpp')
-rw-r--r--usr/src/lib/libpp/Makefile66
-rw-r--r--usr/src/lib/libpp/Makefile.com121
-rw-r--r--usr/src/lib/libpp/THIRDPARTYLICENSE245
-rw-r--r--usr/src/lib/libpp/THIRDPARTYLICENSE.descrip1
-rw-r--r--usr/src/lib/libpp/common/BUGS6
-rw-r--r--usr/src/lib/libpp/common/HISTORY220
-rw-r--r--usr/src/lib/libpp/common/NOTES83
-rw-r--r--usr/src/lib/libpp/common/RELEASE432
-rw-r--r--usr/src/lib/libpp/common/gentab.sh234
-rw-r--r--usr/src/lib/libpp/common/llib-lpp53
-rw-r--r--usr/src/lib/libpp/common/pp.3890
-rw-r--r--usr/src/lib/libpp/common/pp.def282
-rw-r--r--usr/src/lib/libpp/common/pp.h452
-rw-r--r--usr/src/lib/libpp/common/pp.key117
-rw-r--r--usr/src/lib/libpp/common/pp.probe1210
-rw-r--r--usr/src/lib/libpp/common/pp.tab233
-rw-r--r--usr/src/lib/libpp/common/ppargs.c603
-rw-r--r--usr/src/lib/libpp/common/ppbuiltin.c397
-rw-r--r--usr/src/lib/libpp/common/ppcall.c452
-rw-r--r--usr/src/lib/libpp/common/ppcomment.c35
-rw-r--r--usr/src/lib/libpp/common/ppcontext.c65
-rw-r--r--usr/src/lib/libpp/common/ppcontrol.c2295
-rw-r--r--usr/src/lib/libpp/common/ppcpp.c30
-rw-r--r--usr/src/lib/libpp/common/ppdata.c179
-rw-r--r--usr/src/lib/libpp/common/pperror.c38
-rw-r--r--usr/src/lib/libpp/common/ppexpr.c697
-rw-r--r--usr/src/lib/libpp/common/ppfsm.c946
-rw-r--r--usr/src/lib/libpp/common/ppfsm.h278
-rw-r--r--usr/src/lib/libpp/common/ppincref.c49
-rw-r--r--usr/src/lib/libpp/common/ppinput.c721
-rw-r--r--usr/src/lib/libpp/common/ppkey.c118
-rw-r--r--usr/src/lib/libpp/common/ppkey.h146
-rw-r--r--usr/src/lib/libpp/common/pplex.c2441
-rw-r--r--usr/src/lib/libpp/common/pplib.h863
-rw-r--r--usr/src/lib/libpp/common/ppline.c86
-rw-r--r--usr/src/lib/libpp/common/ppmacref.c58
-rw-r--r--usr/src/lib/libpp/common/ppmisc.c242
-rw-r--r--usr/src/lib/libpp/common/ppop.c1553
-rw-r--r--usr/src/lib/libpp/common/pppragma.c66
-rw-r--r--usr/src/lib/libpp/common/ppprintf.c45
-rw-r--r--usr/src/lib/libpp/common/ppproto.c2549
-rw-r--r--usr/src/lib/libpp/common/ppsearch.c807
-rw-r--r--usr/src/lib/libpp/common/ppsym.c94
-rw-r--r--usr/src/lib/libpp/common/pptrace.c264
-rw-r--r--usr/src/lib/libpp/i386/Makefile30
-rw-r--r--usr/src/lib/libpp/i386/pp.req2
-rw-r--r--usr/src/lib/libpp/i386/pp.yacc1
-rw-r--r--usr/src/lib/libpp/i386/ppdebug.h211
-rw-r--r--usr/src/lib/libpp/i386/ppdef.h220
-rw-r--r--usr/src/lib/libpp/i386/pptab.h152
-rw-r--r--usr/src/lib/libpp/mapfile-vers39
-rw-r--r--usr/src/lib/libpp/sparc/Makefile30
-rw-r--r--usr/src/lib/libpp/sparc/pp.req2
-rw-r--r--usr/src/lib/libpp/sparc/pp.yacc1
-rw-r--r--usr/src/lib/libpp/sparc/ppdebug.h211
-rw-r--r--usr/src/lib/libpp/sparc/ppdef.h220
-rw-r--r--usr/src/lib/libpp/sparc/pptab.h152
57 files changed, 22033 insertions, 0 deletions
diff --git a/usr/src/lib/libpp/Makefile b/usr/src/lib/libpp/Makefile
new file mode 100644
index 0000000000..4091cfcbbf
--- /dev/null
+++ b/usr/src/lib/libpp/Makefile
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+SHELL=/usr/bin/ksh
+
+include ../Makefile.lib
+
+SUBDIRS = $(MACH)
+#$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+
+.KEEP_STATE:
+
+all clean clobber install lint _msg: $(SUBDIRS)
+
+LIBRARY= libpp.a
+
+HDRS= \
+ pp.h \
+ ppkey.h
+
+HDRDIR32= common
+HDRDIR64= common
+include ../Makefile.asthdr
+
+install_h: $(ROOTHDRS)
+
+# We don't check these header files because they're owned by AT&T/AST
+check:
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/lib/libpp/Makefile.com b/usr/src/lib/libpp/Makefile.com
new file mode 100644
index 0000000000..f9a16b9af1
--- /dev/null
+++ b/usr/src/lib/libpp/Makefile.com
@@ -0,0 +1,121 @@
+#
+# 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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+SHELL=/usr/bin/ksh
+
+LIBRARY= libpp.a
+VERS= .1
+
+OBJECTS= \
+ ppargs.o \
+ ppbuiltin.o \
+ ppcall.o \
+ ppcomment.o \
+ ppcontext.o \
+ ppcontrol.o \
+ ppcpp.o \
+ ppdata.o \
+ pperror.o \
+ ppexpr.o \
+ ppfsm.o \
+ ppincref.o \
+ ppinput.o \
+ ppkey.o \
+ pplex.o \
+ ppline.o \
+ ppmacref.o \
+ ppmisc.o \
+ ppop.o \
+ pppragma.o \
+ ppprintf.o \
+ ppproto.o \
+ ppsearch.o \
+ pptrace.o
+
+include ../../Makefile.astmsg
+
+include ../../Makefile.lib
+
+# mapfile-vers does not live with the sources in in common/ to make
+# automated code updates easier.
+MAPFILES= ../mapfile-vers
+
+# Set common AST build flags (e.g., needed to support the math stuff).
+include ../../../Makefile.ast
+
+LIBS = $(DYNLIB) $(LINTLIB)
+LDLIBS += -last -lc
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+SRCDIR = ../common
+
+# We use "=" here since using $(CPPFLAGS.master) is very tricky in our
+# case - it MUST come as the last element but future changes in -D options
+# may then cause silent breakage in the AST sources because the last -D
+# option specified overrides previous -D options so we prefer the current
+# way to explicitly list each single flag.
+CPPFLAGS = \
+ $(DTEXTDOM) $(DTS_ERRNO) \
+ -I. \
+ -I$(ROOT)/usr/include/ast \
+ -D_PACKAGE_ast \
+ '-DUSAGE_LICENSE=\
+ "[-author?Glenn Fowler <gsf@research.att.com>]"\
+ "[-copyright?Copyright (c) 1986-2007 AT&T Knowledge Ventures]"\
+ "[-license?http://www.opensource.org/licenses/cpl1.0.txt]"\
+ "[--catalog?libpp]"'
+
+CFLAGS += \
+ $(CCVERBOSE) \
+ -xstrconst
+CFLAGS64 += \
+ $(CCVERBOSE) \
+ -xstrconst
+
+pics/ppcall.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/ppcontrol.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/ppcpp.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/pplex.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/ppexpr.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/ppop.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/ppsearch.o := CERRWARN += -erroff=E_INTEGER_OVERFLOW_DETECTED
+pics/ppsearch.o := CERRWARN += -_gcc=-Wno-sequence-point
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+#
+# libpp is not lint-clean yet; fake up a target. (You can use
+# "make lintcheck" to actually run lint; please send all lint fixes
+# upstream (to AT&T) so the next update will pull them into ON.)
+#
+lint:
+ @ print "usr/src/lib/libpp is not lint-clean: skipping"
+ @ $(TRUE)
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/libpp/THIRDPARTYLICENSE b/usr/src/lib/libpp/THIRDPARTYLICENSE
new file mode 100644
index 0000000000..50c6364c06
--- /dev/null
+++ b/usr/src/lib/libpp/THIRDPARTYLICENSE
@@ -0,0 +1,245 @@
++------------------------------------------------------------------------------+
+| This license covers all software that refers to the URL |
+| http://www.opensource.org/licenses/cpl1.0.txt |
++------------------------------------------------------------------------------+
+
+Common Public License Version 1.0
+
+ THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON
+ PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF
+ THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+ 1. DEFINITIONS
+
+ "Contribution" means:
+
+ a) in the case of the initial Contributor, the initial code and
+ documentation distributed under this Agreement, and
+
+ b) in the case of each subsequent Contributor:
+
+ i) changes to the Program, and
+
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from
+ and are distributed by that particular Contributor. A Contribution
+ 'originates' from a Contributor if it was added to the Program by
+ such Contributor itself or anyone acting on such Contributor's
+ behalf. Contributions do not include additions to the Program
+ which: (i) are separate modules of software distributed in
+ conjunction with the Program under their own license agreement, and
+ (ii) are not derivative works of the Program.
+
+ "Contributor" means any person or entity that distributes the Program.
+
+ "Licensed Patents " mean patent claims licensable by a Contributor
+ which are necessarily infringed by the use or sale of its Contribution
+ alone or when combined with the Program.
+
+ "Program" means the Contributions distributed in accordance with this
+ Agreement.
+
+ "Recipient" means anyone who receives the Program under this
+ Agreement, including all Contributors.
+
+ 2. GRANT OF RIGHTS
+
+ a) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free copyright
+ license to reproduce, prepare derivative works of, publicly
+ display, publicly perform, distribute and sublicense the
+ Contribution of such Contributor, if any, and such derivative
+ works, in source code and object code form.
+
+ b) Subject to the terms of this Agreement, each Contributor hereby
+ grants Recipient a non-exclusive, worldwide, royalty-free patent
+ license under Licensed Patents to make, use, sell, offer to sell,
+ import and otherwise transfer the Contribution of such Contributor,
+ if any, in source code and object code form. This patent license
+ shall apply to the combination of the Contribution and the Program
+ if, at the time the Contribution is added by the Contributor, such
+ addition of the Contribution causes such combination to be covered
+ by the Licensed Patents. The patent license shall not apply to any
+ other combinations which include the Contribution. No hardware per
+ se is licensed hereunder.
+
+ c) Recipient understands that although each Contributor grants the
+ licenses to its Contributions set forth herein, no assurances are
+ provided by any Contributor that the Program does not infringe the
+ patent or other intellectual property rights of any other entity.
+ Each Contributor disclaims any liability to Recipient for claims
+ brought by any other entity based on infringement of intellectual
+ property rights or otherwise. As a condition to exercising the
+ rights and licenses granted hereunder, each Recipient hereby
+ assumes sole responsibility to secure any other intellectual
+ property rights needed, if any. For example, if a third party
+ patent license is required to allow Recipient to distribute the
+ Program, it is Recipient's responsibility to acquire that license
+ before distributing the Program.
+
+ d) Each Contributor represents that to its knowledge it has
+ sufficient copyright rights in its Contribution, if any, to grant
+ the copyright license set forth in this Agreement.
+
+ 3. REQUIREMENTS
+
+ A Contributor may choose to distribute the Program in object code form
+ under its own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+
+ b) its license agreement:
+
+ i) effectively disclaims on behalf of all Contributors all
+ warranties and conditions, express and implied, including
+ warranties or conditions of title and non-infringement, and implied
+ warranties or conditions of merchantability and fitness for a
+ particular purpose;
+
+ ii) effectively excludes on behalf of all Contributors all
+ liability for damages, including direct, indirect, special,
+ incidental and consequential damages, such as lost profits;
+
+ iii) states that any provisions which differ from this Agreement
+ are offered by that Contributor alone and not by any other party;
+ and
+
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable
+ manner on or through a medium customarily used for software
+ exchange.
+
+ When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+
+ b) a copy of this Agreement must be included with each copy of the
+ Program.
+
+ Contributors may not remove or alter any copyright notices contained
+ within the Program.
+
+ Each Contributor must identify itself as the originator of its
+ Contribution, if any, in a manner that reasonably allows subsequent
+ Recipients to identify the originator of the Contribution.
+
+ 4. COMMERCIAL DISTRIBUTION
+
+ Commercial distributors of software may accept certain
+ responsibilities with respect to end users, business partners and the
+ like. While this license is intended to facilitate the commercial use
+ of the Program, the Contributor who includes the Program in a
+ commercial product offering should do so in a manner which does not
+ create potential liability for other Contributors. Therefore, if a
+ Contributor includes the Program in a commercial product offering,
+ such Contributor ("Commercial Contributor") hereby agrees to defend
+ and indemnify every other Contributor ("Indemnified Contributor")
+ against any losses, damages and costs (collectively "Losses") arising
+ from claims, lawsuits and other legal actions brought by a third party
+ against the Indemnified Contributor to the extent caused by the acts
+ or omissions of such Commercial Contributor in connection with its
+ distribution of the Program in a commercial product offering. The
+ obligations in this section do not apply to any claims or Losses
+ relating to any actual or alleged intellectual property infringement.
+ In order to qualify, an Indemnified Contributor must: a) promptly
+ notify the Commercial Contributor in writing of such claim, and b)
+ allow the Commercial Contributor to control, and cooperate with the
+ Commercial Contributor in, the defense and any related settlement
+ negotiations. The Indemnified Contributor may participate in any such
+ claim at its own expense.
+
+ For example, a Contributor might include the Program in a commercial
+ product offering, Product X. That Contributor is then a Commercial
+ Contributor. If that Commercial Contributor then makes performance
+ claims, or offers warranties related to Product X, those performance
+ claims and warranties are such Commercial Contributor's responsibility
+ alone. Under this section, the Commercial Contributor would have to
+ defend claims against the other Contributors related to those
+ performance claims and warranties, and if a court requires any other
+ Contributor to pay any damages as a result, the Commercial Contributor
+ must pay those damages.
+
+ 5. NO WARRANTY
+
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
+ PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
+ WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
+ OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
+ responsible for determining the appropriateness of using and
+ distributing the Program and assumes all risks associated with its
+ exercise of rights under this Agreement, including but not limited to
+ the risks and costs of program errors, compliance with applicable
+ laws, damage to or loss of data, programs or equipment, and
+ unavailability or interruption of operations.
+
+ 6. DISCLAIMER OF LIABILITY
+
+ EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR
+ ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
+ WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
+ DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ 7. GENERAL
+
+ If any provision of this Agreement is invalid or unenforceable under
+ applicable law, it shall not affect the validity or enforceability of
+ the remainder of the terms of this Agreement, and without further
+ action by the parties hereto, such provision shall be reformed to the
+ minimum extent necessary to make such provision valid and enforceable.
+
+ If Recipient institutes patent litigation against a Contributor with
+ respect to a patent applicable to software (including a cross-claim or
+ counterclaim in a lawsuit), then any patent licenses granted by that
+ Contributor to such Recipient under this Agreement shall terminate as
+ of the date such litigation is filed. In addition, if Recipient
+ institutes patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Program
+ itself (excluding combinations of the Program with other software or
+ hardware) infringes such Recipient's patent(s), then such Recipient's
+ rights granted under Section 2(b) shall terminate as of the date such
+ litigation is filed.
+
+ All Recipient's rights under this Agreement shall terminate if it
+ fails to comply with any of the material terms or conditions of this
+ Agreement and does not cure such failure in a reasonable period of
+ time after becoming aware of such noncompliance. If all Recipient's
+ rights under this Agreement terminate, Recipient agrees to cease use
+ and distribution of the Program as soon as reasonably practicable.
+ However, Recipient's obligations under this Agreement and any licenses
+ granted by Recipient relating to the Program shall continue and
+ survive.
+
+ Everyone is permitted to copy and distribute copies of this Agreement,
+ but in order to avoid inconsistency the Agreement is copyrighted and
+ may only be modified in the following manner. The Agreement Steward
+ reserves the right to publish new versions (including revisions) of
+ this Agreement from time to time. No one other than the Agreement
+ Steward has the right to modify this Agreement. IBM is the initial
+ Agreement Steward. IBM may assign the responsibility to serve as the
+ Agreement Steward to a suitable separate entity. Each new version of
+ the Agreement will be given a distinguishing version number. The
+ Program (including Contributions) may always be distributed subject to
+ the version of the Agreement under which it was received. In addition,
+ after a new version of the Agreement is published, Contributor may
+ elect to distribute the Program (including its Contributions) under
+ the new version. Except as expressly stated in Sections 2(a) and 2(b)
+ above, Recipient receives no rights or licenses to the intellectual
+ property of any Contributor under this Agreement, whether expressly,
+ by implication, estoppel or otherwise. All rights in the Program not
+ expressly granted under this Agreement are reserved.
+
+ This Agreement is governed by the laws of the State of New York and
+ the intellectual property laws of the United States of America. No
+ party to this Agreement will bring a legal action under this Agreement
+ more than one year after the cause of action arose. Each party waives
+ its rights to a jury trial in any resulting litigation.
+
+Copyright (c) 2004 by the Open Source Initiative
+This is a copy of the license posted on 2004-10-06 at:
+ http://www.opensource.org/licenses/cpl
diff --git a/usr/src/lib/libpp/THIRDPARTYLICENSE.descrip b/usr/src/lib/libpp/THIRDPARTYLICENSE.descrip
new file mode 100644
index 0000000000..e82817ee4d
--- /dev/null
+++ b/usr/src/lib/libpp/THIRDPARTYLICENSE.descrip
@@ -0,0 +1 @@
+AT&T ADVANCED SOFTWARE TECHNOLOGY PREPROCESSOR LIBRARY (LIBPP)
diff --git a/usr/src/lib/libpp/common/BUGS b/usr/src/lib/libpp/common/BUGS
new file mode 100644
index 0000000000..1d3304d103
--- /dev/null
+++ b/usr/src/lib/libpp/common/BUGS
@@ -0,0 +1,6 @@
+libpp bug list
+
+01/22/93 gsf "" join drops trailing newline of last token in last file
+06/11/92 gsf spurious empty character constant warning for shipproto.c
+02/29/92 gsf "" join bombs if next line is #ident
+02/01/87 gsf a/**/b doesn't concatenate outside macro bodies (COMPATIBILITY)
diff --git a/usr/src/lib/libpp/common/HISTORY b/usr/src/lib/libpp/common/HISTORY
new file mode 100644
index 0000000000..37d9156541
--- /dev/null
+++ b/usr/src/lib/libpp/common/HISTORY
@@ -0,0 +1,220 @@
+libpp change history
+
+ ----- minor sync release -----
+09/11/89 add extra sun style 1,2 arg to line syncs in ppline with pp:linetype
+ add pp:oldc to convert __STDC__ void* and prototypes to old C
+08/11/89 fix <...> include dir bug
+08/08/89 add SYM_INIT for #define during INIT
+07/28/89 delete STRIPTOP, STRIP only T_STRING & T_CHARCONST at pp.level==1
+ add ppcargs() compatibility command line argument parse
+07/17/89 dialect: ANSI (default) or (Reiser) compatibility
+ style: extended (default) or strict
+ use pathprobe(3) for dynamic ppdefault.h
+ add PP_PROBE to specify pathprobe() processor
+ add -[DI]+ to invert options in ppargs()
+ delete PP_ANSI, PP_DIALECT, PP_INITDIR, PP_LANGUAGE
+ delete PP_NONHOSTED, PP_NOPASSTHROUGH, PP_PHASEOUT
+ add #pragma's for most ppargs() options
+ add #option(pragma-option) predicate test
+ PP_MACREF now called during initialization
+07/11/89 add PP_BUILTIN for external #(...) handler
+ add line number to missing endif message
+ ignore errors in skipped ppexpr() &&, || and ?: subexpressions
+ add space before macro actual in replacement text
+07/04/89 fix PP_TRUNCATE interaction with PP_COMPILE
+06/30/89 #define x #; x was recognized as directive #
+06/27/89 don't pass comments during #if skip
+05/01/89 add L"..." and L'...' wide quoted constants
+ mixed "..." and L"..." ok -- L"..." for COMPILE, first otherwise
+ fix PASSCOMMENTS in directives
+ allow #define f(a,) for COMPATIBILITY
+ fix literal string concatenation bugs
+ fix header parsing in non-active if-blocks
+ #endmac now takes no arg
+04/11/89 tone down unknown directive diagnostic in conditional
+04/07/89 move macref call before arg processing
+03/27/89 fix pplex bug that bombed line sync for last line == #include
+03/15/89 fix PP_TRUNCATE macro id bit table checks
+ remove compatibility option s from ppargs() -- belongs in cmds
+03/08/89 remove ``empty character constant'' warning for PASSTHROUGH
+02/28/89 fix variable n usage conflict for DEFINE: in ppcontrol
+02/22/89 fix -T conflict with __GNUC__ in ppargs
+02/01/89 add -T (PP_TRUNCATE) for old non-flexname compiler compatibility
+01/31/89 -I-M-<char><suffix> finds map file by mapping input file name
+ -I-H[directory] allowed for fine hosted control
+01/24/89 fix #undef of SYM_READONLY macro message
+ add PPCOMPATIBLE for compatibility installation in /lib/cpp
+ add PP_MAP & -I-M to map include files for minimal including
+01/18/89 fix pp.token setting by noting with pp.state|=TOKENSET
+01/11/89 fix #if skip bug where quoted token set begin line state
+12/11/88 add error checking wrappers to *alloc()
+12/05/88 add PP_FILEDEPS (-M) and FILEDEPS mode for BSD compatibility
+12/01/88 add #macdef-#endmac and change actualsync() char to SYNC ('\r')
+11/30/88 TOKOUTBUF controls 11/28/88 STANDALONE speedup
+11/28/88 speed up STANDALONE by avoiding pp.token copy
+11/22/88 add comment removal to string_special
+11/11/88 LIBEXPR enables expr(3) in ppexpr() (12K extra text)
+10/11/88 move VARQUOTE to pp.mode
+10/01/88 allow checkpoint files for !STANDALONE
+08/31/88 add pp.undefsym for pp.macref's on undefined symbols
+08/23/88 0xe+N -> `0xe' `+' `N'
+08/16/88 fix ppckeys.c: T_DOUBLE->T_DOUBLE_T, T_FLOAT->T_FLOAT_T
+07/17/88 add \newline to string_special
+ add line number arg to pp.comment call
+ move private stuff from pp.h to pplib.h
+ add ignored -v to ppargs() (GNU uses this)
+06/22/88 move pp.macref check; stack pp.state in ppcontrol()
+ add PP_INCREF and (*pp.incref)(old-file, new-file, push|return)
+06/11/88 add pp.macref
+ add ppckeys.h and C, C++ and pcc-based C keyword tables
+06/01/88 convert to new hash library interface
+05/31/88 pp:readonly in PP_INIT only for STRICT
+05/11/88 T_MOREARGS -> T_VARIADIC; add SYM_VARIADIC for ... last macro arg
+05/03/88 fix empty include file bug by omitting empty check
+04/27/88 ignore space in pragma % maps to accomodate SCCS %.% expansion
+04/19/88 change pp.h to check for old nmake cpp clash with ppsymbol
+04/11/88 fix flag check bug in ppload()
+02/29/88 add MAP_ECHO and %E for MAP_RESCAN + echo
+ PP_INITDIR inserted before PP_STANDARD during initialization
+02/18/88 ignore malformed #'s in COMPATIBILITY macro definitions
+ add pp.prefix, PP_PREFIX and -I-P for prefix dir "..." includes
+02/10/88 add NOQUOTE to disable ' and " and decouple from VARQUOTE
+ add keyword and quote pragmas
+02/02/88 add strcmp builtin predicate for token string value comparison
+01/24/88 fix <backslash><newline> handling in #define on bsd
+01/20/88 add %T and fix %[...] pragma mapping formats
+01/11/88 complete 12/11/87 COMPATIBILITY macro arg /**/ pasting bug fix
+ complete KEYWORD support
+01/08/88 add PP_KEYWORD, (pp.state & KEYWORD), -D-K and #if KEYARGS
+01/06/88 hex char constants are now variable length
+01/04/88 do not add terminator for COMPATIBILITY " and ' constants
+12/11/87 remove #multiple in lieu of #pragma multiple
+ add %R MAP_RESCAN option to rescan pragma/directive mapping
+ fix COMPATIBILITY macro arg /**/ pasting bug
+12/08/87 recode for updated hash library interface
+ add T_PTRMEMREF ->* and T_DOTREF .* C++ operator tokens
+12/01/87 reorganize pp token numbers to span 0401..0477
+11/22/87 add operand error checks to ppexpr()
+ add PP_DEFAULT and -I-Dfile for fine PPDEFAULT control
+11/11/87 pppragma() now omits space after # for primitive passes (uts)
+10/30/87 fix line count on `newline' in ['"] constant warning
+10/29/87 add MAP_PLUSCOMMENT and %P to pragma|directive mapping
+10/28/87 add head & tail args to ppcomment; pass // comments as is
+10/23/87 add warning for multiple ppop(PP_LOCAL) calls
+10/16/87 change PP_HOSTED to PP_HOSTDIR, add PP_HOSTED and PP_NONHOSTED
+ add #(BASE) that expands to base name of #(FILE)
+10/15/87 for PASSTHROUGH each line of multi-line "..." or '...' is a token
+10/14/87 add ppmultiple() for multiple include test ops
+10/11/87 delete CONVERTASSIGN -> `=<op>' no longer recognized
+ delete C++ := -> = conversion
+ fix COMPATIBILITY macro recursion bug
+ add `#pragma multiple' equivalent to `#multiple'
+10/06/87 split pplex.c adding ppdirective.c and ppbuiltin.c
+ don't recognize obsolete assignments for PLUSPLUS
+10/05/87 fix PLUSPLUS PASSCOMMENTS bug `// */' -> `/* ***/'
+10/01/87 allow newlines in ' and " constants for PASSTHROUGH
+09/28/87 fix CONVERTCC STRICT bug that omitted octal character constants
+ add CATLITERAL compile switch for adjacent string literal concatenation
+ fix "\07" "3" -> "\073" string literal concatenation bug -> "\0073"
+09/18/87 complete ppdump() and ppload() checkpoint support
+09/17/87 fix macro formal bug that didn't update pointers after realloc()
+ add PP_DONE complement op to PP_INIT
+ add SYM_BUILTIN and #pragma pp:builtin to note builtin macros
+ add PP_DUMP, -D-D and #pragma pp:load checkpoint support
+08/20/87 fix bug that omitted some actualsync() calls for '\n' in pp.in->actual
+08/19/87 fix pp.linesync==0 && PASSTHROUGH bug that omitted '\n' after "token"
+08/11/87 fix #($var) null pointer bug
+07/31/87 fix linesync bug for comment after #include in PASSCOMMENTS
+07/24/87 add PP_NOPASSTHROUGH
+07/16/87 fix predicate missing # ambiguity warning
+07/09/87 fix `macro("@*")' bug in expand_special()
+06/17/87 fix comment error message check that was off by one line
+06/16/87 remove #pragma pp:multiple; add #multiple; retain PP_MULTIPLE
+06/08/87 add # operator to disambiguate predicate tests
+ inhibit more warnings on hosted files
+ make diagnostics more consistent -- a little more work
+ PP_READ files and their included files always marked hosted
+06/05/87 fix macro actual arg collection with imbedded #include, #line
+05/28/87 add `#pragma pp:multiple *' to mark all files multiple
+ add -D-M for command line equivalent to `#pragma pp:multiple *'
+05/01/87 clarify HOSTED and SYM_PREDEFINED
+04/24/87 split pplex.c into smaller files -- too big for some compilers
+ move common wrapper routines into the library
+ fix ppargs() to cooperate with other option parsers
+04/22/87 remove getenv("PPSTANDARD") override of PP_STANDARD
+04/21/87 replace yacc parser with recursive expr() from library streval()
+04/20/87 add #((<expr>)) expression evaluation on (x)
+ add #(<sym>=<expr>) to dynamically evaluate macro values
+04/11/87 home brew output buffering for PP_STANDALONE -- up to 10%
+ cleanup
+04/10/87 change T_STRING concatenation in preparation for new output buffering
+04/09/87 fix character constant conversion warnings
+04/07/87 fix \\n and ??/\n bugs in comment scan
+04/06/87 add DIGIT, HEX, OCTAL and NONOCTAL case classes to ppdefs.h
+ use GETCHR() and ISSPECIAL() in outer pplex() loop -- up to 10%
+ fix macro actual arg count test
+04/03/87 add PP_TEST and TEST1, TEST2 to mode for internal tests
+04/02/87 delete PPDEFAULT and generalize with PP_READ
+ note `# <line> "<file>"' as non-standard
+ add check for malloc() out of space
+04/01/87 C specific error messages only if language="C"
+ C++ specific error messages only if language="C++"
+03/31/87 delete command() predicate -- gateway for trojan horse
+03/30/87 add dialect() and language() builtin predicates
+ change in->standard to in->hosted and STANDARD to HOSTED
+ add PP_HOSTED and change PP_NOSTANDARD to PP_NOHOSTED
+ ignore #pragma for non-hosted files in STRICT dialect
+03/27/87 add predop(); delete pp:plusplus
+ pp:dialect and pp:language for verification only
+03/24/87 ----- first release -----
+03/24/87 ----- first release -----
+03/23/87 allow WARN to apply to all dialects
+ fix pp:directive `...multiple...' warning
+ add MAP_NEWLINE to separate multiple pragmas
+03/22/87 warn about null macro args for STRICT
+ add PP_LANGUAGE, `#pragma language [language]'
+ warn about newline in macro call arguments in directives
+ warn about directives in macro call arguments for STRICT
+ validate character constants in #if expressions
+03/20/87 add PP_DIRECTIVE and PP_LOCAL
+ add %I (ignore) map format and allow %X for pragma args
+03/19/87 change PP_DEFAULT to PP_STANDARD, add PP_DIALECT
+ add dialect arg to PP_COMPATIBILITY, PP_DIALECT and PP_STRICT
+ add `#pragma pp:pragma pass:option format' mapping
+03/18/87 delete pp:obsolete; fix `#pragma version'
+ fixed macro stack frame bug during recursive macro arg expansion
+ change CONFORMING, PP_CONFORMING to STRICT, PP_STRICT
+ add `#pragma dialect [dialect]' verification
+03/17/87 add PP_NOSTANDARD to disable any special handling of std files
+ refine mkdefault.sh for sun workstations
+ remove comma operator from pp.yacc since it implies side effects
+ add argument type checking for pp:directive and pp:obsolete
+03/16/87 refine CONFORMING messages
+ disambiguate most #assert/#define clashes
+ add PASSCOMMENT and (*ppcomment)() for old lint fans
+03/14/87 #undef in pp:readonly marks id as readonly macro
+03/11/87 warn about macros that are predicates in #if expressions
+ add mode to handle uncoupled flag bit overflow from state
+03/04/87 fix COMPATIBILITY to expand a macro in its definition
+02/24/87 add gentab.sh and mkdefault.sh to Makefile
+02/20/87 add IN_RECURSIVE for proper handling of #(...)
+02/16/87 add #unassert; PP_WARN & WARN to note obsolete usage
+ only recognize directive if # is first char for (state&COMPATIBILITY)
+ generalize gentab.sh and retrofit pp.tab
+ change in->name.file to be the name of including file
+02/13/87 add pp.tab; PP_PRAGMA "x=y" -> "#pragma x y"
+ add #(x y...) -> "#x y..." for recursive directive evaluation
+02/12/87 #pragma [pass:] [no]option [arg ...]
+ #pragma pp:[no]directive [pass:]<new-directive>
+ #pragma pp:id <identifier-character>
+02/11/87 distribute post-token switch in pplex() to individual cases (~5%)
+02/09/87 clarify invalid numeric token gobble
+ add VARQUOTE & PP_VARQUOTE for `X...X vs. '...' & "..." constants
+02/06/87 change STRICT to CONFORMING; add PP_CONFORMING
+02/06/87 change PPBUILTIN to #(<id>)
+02/05/87 clarify /*...*/ concatenation for (state&COMPATIBILITY)
+ add convertcc() to convert new char const to old style
+ rework # op to work with convertcc()
+02/04/87 add =<op> obsolete operators for (state&COMPATIBILITY)
+02/02/87 fix expand() to save and restore (state&DISABLE)
+12/17/86 first code
diff --git a/usr/src/lib/libpp/common/NOTES b/usr/src/lib/libpp/common/NOTES
new file mode 100644
index 0000000000..85ab42e74b
--- /dev/null
+++ b/usr/src/lib/libpp/common/NOTES
@@ -0,0 +1,83 @@
+C preprocessor features:
+
+(1) The preprocessor is centered around the libpp.a library. This
+ library provides a tokenizing implementation of the preprocessing
+ stages of ANSI standard C. The same library is used to construct
+ a standalone prepreprocessor as well as a C compiler front end
+ that, compiled with the library, eliminates the need for a
+ separate preprocessing pass. Other C tools requiring C tokenizing
+ can use this library, providing a common interface to C language
+ tokens.
+
+(2) The #pragma interface is exploited to allow the addition of new
+ directives and #pragma's without changing the preprocessor
+ executable. Most implementation details can be specified by
+ directives in the file "ppdefault.h" that is automatically included
+ (by the standalone cpp library wrapper) as an initialization step.
+
+(3) #assert, #unassert and corresponding #if predicate tests have been
+ added to relieve the conflicts introduced by predefined #define
+ macros (e.g., unix, vax, u3b, ...). This is the same feature
+ present in the extended Reiser cpp that has been included in the
+ nmake distribution. (NOTE: #assert is a failed experiment)
+
+(4) The implementation is sensitive to the incompatible differences
+ between the Reiser cpp (used by AT&T and BSD compilers) and the new
+ ANSI standard C. A compatibility dialect implements Reiser
+ features, allowing for a smooth transition to the ANSI standard.
+
+(5) To aid in the transition to ANSI, the preprocessor can do some
+ operations that would normally be done by the lexical analysis
+ stage of a compiler front end:
+
+ (a) convert new-style character constants to a form
+ recognized by all current compilers
+
+ (b) concatenate adjacent string literals
+
+(6) The preprocessor can also warn about obsolete constructs used
+ in the compatibility dialect and on non-standard constructs
+ used in the ANSI dialect. The latter is useful in writing
+ C code that is made to run through other implementations of
+ ANSI standard C.
+
+(7) The preprocessor allows a C language implementor to take
+ advantage of local extensions without invalidating the
+ conformance of the C language implementation.
+
+C9X additions:
+
+(1) #pragma STDC ...
+ special forms always accecpted
+
+(2) _Pragma unary operator for pragmas via macro expansion
+ _Pragma(string-literal)
+ #pragma a b c
+ _Pragma("a b c")
+
+(3) keywords
+ restrict inline _Bool _Complex _Imaginary
+
+(4) macros
+ __STDC_VERSION__ 199901L
+ __STDC_IEC_559__ 1 or undef
+ __STDC_IEC_559_COMPLEX__ 1 or udef
+ __STDC_ISO_10646__ yyyymmL
+
+(5) empty arguments allowed in function-like macros
+
+(6) variable arguments via ...
+ __VA_ARGS__ in replacement list only, expands to var args
+ only var args is ok (shall only appear in ...)
+
+(7) hex floating constant with binary exponents
+ xxxxxx[pP]dddd
+
+(8) // style comments
+
+(9) universal characters, even in identifiers!
+ \uxxxx \Uxxxxxxxx
+
+(10) LL ll ULL ull suffix for long long literals
+
+(11) <stdarg.h> has va_copy()
diff --git a/usr/src/lib/libpp/common/RELEASE b/usr/src/lib/libpp/common/RELEASE
new file mode 100644
index 0000000000..179930e147
--- /dev/null
+++ b/usr/src/lib/libpp/common/RELEASE
@@ -0,0 +1,432 @@
+06-09-23 ppop.c: check -I <dev,ino> for c and TYPE_HOSTED|TYPE_VENDOR attrs
+06-09-23 pplex.c: add HOSTED check for "/* appears in // comment" -- doh
+06-09-05 pp.probe: add version stamp comment
+06-06-29 pp.probe: gcc pp:linefile probe (otherwise it can dump!)
+06-06-28 ppproto.c: fix inappropriate __PARAM__ insertion
+06-05-09 pp.tab,ppcontrol.c,ppproto.c: add externalize
+ ppfsm.c: handle compatibility ul numeric qualifiers
+06-02-28 probe.win32: add wchar_t probe
+06-01-11 pplex.c: fix rpcgen pp:passthrough header splice bug
+05-12-16 pplex.c: fix imake pp:passthrough comment splice bug
+05-09-16 pplib.h: add <string.h> for standalone proto
+05-07-31 pplib.h: finally trust __STDC__ headers
+05-04-11 pplex.c: fix '"a" #s' catliteral + stringize bug
+05-03-29 pp.probe: check $? and stderr messages for pp:lineid
+05-02-20 probe.win32: handle /platformsdk mount
+05-01-11 ppargs.c: fix -I-S docs
+ ppinput.c: ppproto() only for COMPATIBILITY or PLUSPLUS
+04-10-22 ppproto.c: handle `type var[x][y]' arg prototype
+04-10-01 pplex.c: really fix directive hidden newline logic
+04-08-31 pplex.c: fix directive hidden newline logic
+ ppcall.c: fix '(' peek bug that missed the MARK
+04-08-30 add pragma pp:pragmaflags PP_PRAGMAFLAGS, pp:system_header
+04-08-11 ppproto.c: intercept "#(define|undef) extern" for __(EX|IM)PORT__
+04-07-23 probe.win32: generalize #include dir order search
+04-07-22 ppsearch.c: access() => eaccess()
+04-05-20 ppproto.c: don't __PROTO__ `int fun __P((int));'
+04-04-15 probe.win32: sync up with uwin 2003-08-06 master -- oops
+04-04-01 pp.probe: add stdinclude usrinclude path cleanup
+04-02-29 ppproto.c: fix bug that skipped prototyped check during notices check
+ ppproto.c: recognize `Copyright nn'
+04-02-14 ppproto.c: comment[0]==0 => no notice
+04-02-11 Makefile: fix %.yacc to handle cross-compile
+04-01-28 pp.h,pplib.h,ppop.c: add PP_RESET to restore original pp.symtab scope
+03-12-12 ppcall.c: missing macro actual warned but expanded
+03-11-12 ppexpr.c: fix premature #if expression token strip
+03-06-21 ppproto.c: fix T_INVALID ? splice bug that did 0?val => 0?vaL
+03-06-10 ppargs.c: add -D-d and -D-m
+ ppargs.c: add gnu options { -dD -dM -imacros -include -lang-* -lint }
+03-05-19 pplex.c: fix stray SKIPMACRO bug
+03-05-18 ppcall.c: add SYM_FUNCTION '(' peek to avoid inappropriate ungetchr()
+03-04-30 pp:mapinclude hosted <std.h>="." will search only hosted dirs
+ pp.probe: add pp:mapinclude probe for namespace incursions
+03-04-29 ignore()=>ppmapinclude(), add pp:mapinclude
+03-03-25 ppop.c: PP_RESERVED now deletes old symbol before redef with lex value
+03-03-14 pp.probe: fix the #include_next probe
+03-02-28 ppsearch.c: fix -MM bug that missed prefix include hosted mark
+03-02-18 pplex.c: handle COMPATIBILITY \" and \' in macro actuals
+03-01-23 probe.win32: mingw32 tweaks
+02-12-17 ppargs.c: document -I-!
+02-12-06 -I- pp:noprefix otherwise pp:prefix default
+02-11-29 probe.win32: added __INTSIZE, drop dm pp:noallmultiple
+02-11-26 pp.def: add STDC_HOSTED
+ probe.win32: add C95 and C99 STDC predefined macros
+02-10-30 ppfsm.h: add boundary check to IDSTATE()
+02-10-18 probe.win32: update for mingw
+02-10-15 ppsearch.c: if PLUSPLUS && not found && no suffix then try with .h
+02-10-10 pplex.c: fix does not end with `newline' bugs
+02-10-01 ppop.c,ppargs.c: -I-I => -I-M with proper docs; -I-I for PP_IGNORE
+02-09-21 pp.probe: add pp:nocatliteral test
+02-09-10 pp.tab: add pp:passthrough to match -D-P docs
+02-08-30 probe.win32: fix for borland cc -E
+02-08-22 ppexpr.c: add __SOURCE__ and #match(string,pattern)
+02-06-25 ppproto.c: fix pragma search bug that stopped after 8 comment lines
+02-06-11 ppsearch.c: fix ... next include search to skip *all* intermediates
+02-05-28 probe.win32: updates for { mingw }
+ ppsearch.c: don't use inherited prefix for <...> -- duh
+02-05-24 ppcontrol.c: simplify getline() space canonicalization
+ probe.win32: updates for { digital-mars borland lcc }
+02-05-20 ppcontrol.c: update to use regsubcomp(),regsubexec()
+02-05-09 ppcontrol.c: inhibit `EOF in directive': newline warning will catch it
+ pplex.c: inhibit `newline in character constant' for hosted directives
+02-05-06 probe.win32: add more win32 compilers
+02-04-15 probe.win32: handle long long unsigned int
+02-04-12 ppproto.c: fix NOTICED check
+02-03-15 ppproto.c: fix cpp pp:compatibility double line sync memory fault
+02-03-11 pplex.c: add pp:modern to emit \a \v instead of octal forms
+02-02-14 ppargs.c: fix -D or -U as last arg core dump
+02-01-24 pplib.h: use vmalloc(Vmregion) if _std_malloc
+02-01-23 probe.win32: add more msvc predefined macro candidates
+02-01-14 ppproto.c: #pragma prototyped noticed -- has notice comment
+02-01-10 ppproto.c: fix PROTO_FORCE|PROTO_PASS bug that disabled PROTO_FORCE
+02-01-08 pplex.c: fix HEADEREXPAND|HEADEREXPANDALL logic
+01-11-22 pplex.c: add pp:headerexpandall for gcc vs. msvc <...> expand diff
+ pp.probe: add pp:headerexpandall test
+01-10-20 pplex.c: fix pp:splicespace inside "..."
+01-09-11 ppinput.c: use pathnative() for native fs representation
+01-08-31 pp.probe: handle -Dmacro(args)=value
+01-08-11 ppcontrol: fix ... and __VAR_ARGS__ for C99
+ ppsearch: fix SEARCH_NEXT bug that skipped the include stack
+01-08-06 ppproto: preserve #! first line for # comments
+01-07-17 gentab.sh: fix ksh test to omit pdksh (typeset -u fails)
+01-06-26 ppproto.c: fix another buffer boundary bug that didn't preserve OTHER
+01-06-06 ppsearch.c: list PP_FILEDEPS headers once
+01-06-01 pp.h,ppop.c,ppsearch.c: allow multiple PP_FILEDEPS (-M)
+01-05-24 pp.probe: fix pp:hostedtransition probe: only suncc can __STDC__==1?
+01-04-25 pp.probe: split macro probe files for compilers that have #line limits
+01-04-19 pp.h,pplex.c,ppproto.c: fix { \a \E \v } EBCDIC translations
+01-04-16 pp.tab: add pp:splicespace for mvs jcl decks -- the 60's live on
+01-04-13 ppbuiltin: add __FUNCTION__ cache for functions that span the buffer
+01-03-08 pp.tab,ppbuiltin,ppcontrol,probe: add pp:hostedtransition
+01-02-22 pp.tab,ppfsm,pplex,pp.probe,probe.win32: add pp:zeof for ^Z => EOF
+01-02-14 ppcall.c: fix macro(tuple*) bug that truncated macro arg expand buffer
+ pplex.c: fix # inside pp:pragmaexpand
+ gentab.sh: change ksh test for openbsd /bin/sh
+ ppproto.c: fix buffer boundary bug that lost call nesting
+ ppproto.c: add realloc prototype and memcpy=>memcopy strcpy=>strcopy
+01-02-09 ppsearch.c: fix another pp.include null dereference
+01-02-07 ppcall.c: fix stack inequality checks
+ ppcall.c: handle trailing \ in macro args
+01-02-06 fix readonly buffer write (cpp test 07:2873)
+01-02-04 fix -M* to properly handle .cxx .cpp .C input
+ fix IN_BUFFER pop bug that did not reset the token pointer
+01-01-01 pp:headerexpand: space ok if not IN_MACRO
+ ppcall: hide if IN_FILE|IN_MACRO|IN_EXPAND
+ pplex: don't complain about ^L or ^Z as last char in file
+ ppsearch: fix #include <.../foo.h> loop
+ ppcontrol: manulally increment IN_RESCAN error_info.line
+00-12-25 add EXPOSE to expose hidden macros (for #import ...)
+ probe.win32: add cc path *and* args to first line to avoid hash clash
+ pp.probe: filter out invalid symbols for predefined macro scan, duh
+ pp:headerexpand: limit expansion to IN_MACRO
+00-10-31 __STDC__==0 if HOSTED && _UWIN
+00-10-26 pplib.h: change SEEK_SET to O_RDONLY for aix
+00-10-17 pp.probe: __IMPORT__ => __STDPP__IMPORT__
+00-09-18 add __FUNCTION__=#(FUNCTION), #define <a b> c
+ pp.probe: add probe_longlong
+ probe.win32: add #define <long long>
+00-09-11 add pp:noproto (NOPROTO pp.option) to disable ppproto()
+00-09-01 ppproto: fix buffer slide bug
+00-08-11 pplb.h: check for <unistd.h> already included for PROTOMAIN
+ pragma: add pp:pragmaexpand to expand pragma args
+ ppcontrol: always disable pp:* pragma expansion
+ ppcall: fix pp:hide buffer clash
+00-06-01 pplex: fix "\\U" and "\\u"
+00-05-22 ppsearch: fix uwin #include <C:/foo/bar.h>
+00-05-16 probe.win32: update reserved word list
+00-05-09 ppcontrol: fix C++ macro >+> invalid fuse
+ ppcontrol: 'macro' expansion only for COMPATIBILITY | TRANSITION
+ c9x: up to date with proposed standard
+00-04-01 pp.tab: add allpossible and ALLPOSSIBLE
+ ppmacref: fix ref inside literal catenation
+00-02-14 pppopen(): general comments with "bme" (begin middle end) string
+00-01-11 pp.probe: hosttype now in C.probe
+99-11-19 is[a-z]*( => ppis[a-z]*(
+ ppproto: "..." [A-Z_]+ "..." ignores [A-Z_]+ if PROTOMAIN
+99-11-11 ppproto: use astlicense()
+99-10-31 ppproto: add PROTO_SHARP, update license parse
+ pplex: fix some MARK bugs seen by #define X "A B <C@D>"
+99-10-01 add pp:stringsplit for "...\\n..." => "..."\n"..."
+ add pp:lineid to match PP_LINEID
+99-07-17 ppbuiltin: fix getline() canon spacing for numbers
+ ppsearch: fix FILEDEPS not found \\n print
+ pplex: fix spurious FILEDEPS '.' empty character constant message
+ ppargs: fix usage error call and error_info.id default value
+ ppproto: fix up copyright notice for ksh93 style .author file
+ ppproto: check if notice text if file path
+99-06-02 ppproto: add __MANGLE_package_DATA__ & __MANGLE_package_FUNC__
+99-05-26 ppcontrol: all pragmas but prototyped need pp:
+99-05-25 ppargs: long options
+99-05-22 ppproto: changes for full ast vs. PROTO_STANDALONE
+99-05-09 ppinput: add #pragma pp:native and (pp.option&NATIVE) for native paths
+99-04-22 ppproto: finish type=open notice
+99-02-11 #define __STDC__ #(STDC); demote __STDC__ to 0 for HOSTED (thanks sun)
+99-02-04 pplex: joined strings separated by \\\n
+99-01-11 probe.win32: add _UWIN predef
+98-10-20 pplex: a few more (HOSTED|RELAX) checks
+ -D:preserve throws a bunch of stuff -- great for imake (yuk)
+98-05-11 pplex: fix "..." \n off by one line count
+98-02-14 ppcontrol: fix HEADEREXPAND missing NUL
+98-01-23 ppproto: add _GNUC_ to _WIN32 check
+ ppfsm: don't optimize for hp.pa
+97-11-11 ppcontrol: fix recursive use of pp.hdrbuf for HEADEREXPAND
+97-10-31 ppmacref,pp.h: add ppmacref sum arg -- some parts assumed it!
+97-10-01 pplex: loosen HEADEREXPAND check
+97-08-11 pplex: fix COMPILE pplex() bug that did not reset NEWLINE for S_MACRO
+ pplex: PP_PRESERVE does not pp.pragma <token> ... # <pragma-stuff>
+ pp.def: add UWIN
+ ppcall: fix macro actual arg error checks
+97-07-17 ppproto.c: C++ __INLINE__ prefixed with extern __MANGLE__
+ ppop.c: fix PP_RESERVED T_* lookup
+97-05-09 pp.def: add MVS :architecture:
+ ppfsm.c: change C_* pseudo codes to not clash with ebcdic
+ pp.probe: fix stdc.$src sed script
+97-04-01 ppcontrol.c: fix tokop() for PP_RESERVED
+96-12-25 add ms #@ charize to complement # stringize
+ pp.probe now detects preincludes
+ ppproto: allow #ifdef'd function definions before {
+ ppproto: NoN() is not a function
+ pp.key,ppkey.h: add int64
+ ppargs.c: fix -M{DGM}*
+96-12-06 add pp:headerexpand for ms that expands macros in expanded <...>
+96-10-31 a few more line sync tweaks for EDG C++
+96-10-11 fix pp:macref off by one for standalone pp (big suprise)
+96-10-01 -D:macref -D-L -> #line (n-2)\n#pragma pp:macref ...
+96-08-11 fix transition macro expansion
+ compatibility \" or \' does not start quote
+96-02-29 use <hashkey.h>
+ drop ungetchr() in ppcall that modified macro values
+ tighten the DEBUG PANIC case in ppcontrol.c
+ unify #architecture() and #machine() probe
+ add POSIX,WIN32,X86 to pp.sym
+ tweak pp.probe
+96-02-14 pp:noallmultiple works on hosted files too
+ fix #define /* EOF loop
+96-01-31 fix ## as arg to stringize macro to have ## value, not #
+ add nonstopux and SYSTYPE_SVR4 to pp.def
+96-01-01 AT&T Research now
+ fix catliteral line sync line number bug
+ ppproto() converts non-directive <num>u to (unsigned)<num>
+ switch to <regex.h>
+95-10-31 fix PP_COMPILE PP_TRANSITION bug that didn't allow space before #
+ fix PP_TRANSITION \newline in definition complaint
+95-10-11 fix ppproto() PROTO_PLUSPLUS bug
+ change ignored pp.incref PP_SYNC_POP to PP_SYNC_IGNORE
+ add PP_PEDANTIC to handle gnu oversights (can't beat em ...)
+ add memfatal() call
+ relax newline in quote semantics
+ proto inline -> __INLINE__
+ fix __INLINE__ proto def for __GCC__>=2
+95-08-11 pp:preserve for easel (aka IFS) and imake
+ fix pp:reguard ## macro output
+ fix MARK PANIC with CATLITERAL
+ PP_INPUT *.(s|S|as|AS|asm|ASM) implies pp:nocatliteral pp:spaceout
+ ppargs() can't use isid() until after FSM_INIT
+ -D#... for assert, -D%... for directives
+ __STRICT_ANSI__ && __GNUC__ requires -pedantic for PP_STRICT
+ #include <.../x> for include_next
+95-05-09 fix tokop() bug that concatenated adjacent strings
+ don't concatenate directive string literals in proto
+ split pp.mode into pp.mode and pp.option
+ restrict pp.probe hostinfo output to the first token
+ fix EOB/EOF pplex() nonterminating loop
+ unused var cleanup
+ add pp:reguard to emit #define and #undef (for C++ templates)
+ add a few ppproto '\r's for NT
+ fix T_BUILTIN ppsymbol -> ppsymkey pun
+ fix pp:stringspan `#define x "' hang
+95-04-01 fix pp:hide for macros defined before the hide
+ fix pp:map getline space canonicalization
+ fix proto `<digits>[uU]'
+ proto does // comments by default (fixes bug introduced 07/17/94)
+ proto does "..." "..." string literal concatenation
+ spice up proto copyright comments for nonexclusive license
+ add hosttype assertion
+ fix proto `typedef type fun(args)'
+ proto copyright finishing touches
+ fix overzealous "empty character constant" message
+95-02-14 pp:nopredefined probe info defines are now pp:builtin
+ clean up pp:hosted conflicts
+ tighten up unknown directive warning
+ PP_INPUT *.(s|as|AS|asm|ASM) implies pp:nocatliteral pp:spaceout
+ change newof(0,char,n,0) to newof(0,char,0,n) if 0 init not needed
+ don't emit unkown directives inside #if 0 ... #endif
+95-01-19 *strict-* does not force STRICT
+ token##null-last-variadic-arg consumes token (to match gcc)
+ variadic actuals call be one less than arity (to match gcc)
+ fix PLUSPLUS digraph bug that lost comment state
+ tighten up PLUSPLUS //, /*, */ interaction warnings
+ macro formals in "..." for COMPATIBILITY|TRANSITION
+ macro formals in '...' for COMPATIBILITY|TRANSITION|!STRICT
+ STRINGSPAN allows '\n' in '... too
+ add PP_SYNC_* flags for pp.incref arg 3
+ add PP_SYNC_INSERT for invented file references
+ fix C++ fsm bug that popped out of comment in // /* */ ...
+ PP_INPUT *.(s|S|asm|ASM) implies pp:nocatliteral pp:spaceout
+95-01-01 avoid string literal concatenation in pp.probe #if #predicate() tests
+ fix pplib.h memcpy,strncmp PROTOMAIN prototypes (its a nop tho)
+94-11-11 fix readonly memory reference in refill
+ add C++ digraphs (digraph = --trigraph)
+ add C++ T_EXPLICIT -- did dos take over C++?
+ fix improper ppproto() C++ __PARAM__ expansion
+94-11-01 allow #include string header arg concatenation (yes, its not ansi)
+ #macdef macros are recursive
+94-10-01 fix C++ } loop in ppfsm/refill
+ T_NOISES consumes symbol and optional paren group
+ __builtin_* T_NOISES by default
+ fix "..." "...MARK..." join
+ fix STANDALONE */*comment*/
+94-09-11 fix pp.probe cp+strip with chmod u+w
+94-08-11 add -I<vdb-archive> to handle pax -x ppar header archives
+ fix -D-Q header checkpoints
+ add `pp:chop prefix' to chop prefix/ from include prefix/*/*
+ add pp:keyargs for key=value macro formals/actuals (not for C!)
+94-06-01 fix ppcontrol/tokop() that botched pp:id, etc.
+ add pp:plussplice to handle cfront // \<newline> ignorance
+ inhibit trigraph conversion for pp:compatibility, duh
+ new C++ keywords enabled by pp:keyword
+ proto: int fun xxx((yyy)) is macro call, not decl
+ fix !ALLMULTIPLE pp:load to SKIP between duplicated line syncs
+ fix PP_DUMP for pp:noallmultiple, optimize pp:load format
+ fix CPP CACHEOUTX() buffer boundary bug
+94-04-01 drop warnings for -X*
+ fix ppproto() %% in comment bug for yacc proto
+ PP_COMMENT now truncates comments to MAXTOKEN-4
+94-03-01 no pp:truncate for #pragma pp:macref
+94-01-01 fix STANDALONE+PP_TRUNCATE fsm macro bug
+ drop __VOID__ from ppproto.c
+93-12-01 release
+93-11-11 fix PP_COMPILE+PP_TRUNCATE=8 bug for continue,unsigned,etc.
+ add PP_LINEBASE for compilers that botch long line sync paths
+ fix #if unsigned promotions
+ aggressive interactive line splice flush
+ fix #else inside multiline null dereference
+ fix "..." newline space # COMPATIBILITY CATLITERAL bug
+ fix m(a)b compatibility token pasting [cpp/test/ess.01.c]
+ fix nested @X mark bug [cpp/test/net.02.c]
+93-10-11 add FSM_COMPATIBILITY for floating point hex -- yo ansi, anybody home
+ add #else if|ifdef|ifndef for COMPATIBILITY but with warning
+ drop PP_HOSTED, add ppop(PP_CDIR|PP_HOSTED,"-",n), -D-I for pp:cdir
+93-10-01 add pp:opspace to tokenize <binop><space>= to <binop>=
+93-08-11 drop ancient BCD constant (`...`) detection -- wake up cfront
+ fix PP_TRUNCATE macro fsm bug that missed some expansions
+ fix stringize bug that choked if space preceded #
+ fix <function-like-macro> <identifier> bug that omitted space
+93-07-17 minor transition mode fix for string concatenation
+ fix standalone macdef line sync buffer bug
+ pp:noline turns off linesync, pp:line restores it
+93-06-22 add pp:prefix to control prefix include compatibility
+93-04-01 use probe_verbose in predefined symbol probe
+93-03-11 close fd after last file block read -- relaxes open fd limit
+ remove pp.control nesting limit
+ add `#rename old new'
+ __STDC__ not defined for plusplus (until they figure it out)
+93-01-22 fix ansi macro args recursion bug
+93-01-11 fix '\377'<0 for signed char compilers
+ add RELAX for __STDPP__directive directives
+92-12-25 fix #include guard test that omitted IN_tokens for CPP=1
+92-12-11 fix pp:truncate for STANDALONE and COMPILE
+ fix pp:allmultiple again!
+92-11-30 add pp:final, pp:initial
+ add __STDPP__directive and #(directive) as ??= alternative
+ relax obsolete macro expand warning for _xxx||xxx
+ retain quoted \newline when PP_LINEID != ""
+ fix CATLITERAL hidden newline line sync
+92-11-11 fix COMPATIBILITY EOF in macro arg list and # in macro body
+ fix [?\] on 4K buffer boundary bug that lost next refill()
+ fix ppproto bug that botched -ih comments
+92-10-31 fix standalone -C bug that duplicated output buffer
+ add pp:stringspan to handle gnu "<newline>" extension
+92-10-12 fix T_X_GROUP asm bug
+ allow `#define a "b' pp:compatibility hack
+92-08-11 add PP_PLUSCOMMENT, pp:pluscomment probe
+ add #(default v,d) #(empty v) #(iterate m,...)
+ compatibility allows #define f(a,,b) for 2 args!
+ probe now handles gcc -E -g3 to get gnu predefines
+92-07-17 fix pp:multiple again, fix ppproto() out of bounds
+ PP_STANDARD is always PP_CDIR and PP_HOSTED
+92-07-11 add #import and #include_next probes
+92-06-11 fix bug where comments dissappeared after disabled macro in standalone
+ COMPATIBILITY macro recursion bug fix may cause some to be missed
+ PP_MACREF or -D-L- ignores #line until #line with file arg
+92-06-01 add pp:ignore
+ fix probe of stdpp to handle -I[-+][CH]
+92-05-11 add pp:hide <id>, pp:note <id>, noticed(<id>), exists(<...>)
+ add defined(__STDPP__<pragma>) feature test
+ add PP_CDIR, pp:cdir for C++ extern "C" { ... } include wrapping
+ pp.probe now handles predefines with values other than 1
+92-04-11 add inverse proto (K&R -> prototype) to ppproto
+92-04-01 release
+92-02-29 #include <...> inside <xxx.h> gets next xxx.h on -I list
+ non-libpp generated symbols containing ' ' are not truncated
+92-02-11 conversion to new lexer brings time close to reiser (esp. w/gcc -O)
+ combine standalone (ppcpp) tokenizing (pplex) and proto lex tables
+ recode ppproto for standalone operation via PROTOMAIN
+ add PP_NOHASH for PP_COMPILE front ends that rehash T_ID anyway
+ delete PP_NOQUOTE
+ delete #option(strict) test in probe in favor of non-hosted warnings
+ add unsigned to ppexpr()
+91-10-11 add pp:truncate <len> for non-flexname compilers
+91-09-11 fix ppproto aggression on f(*y); -> f __PROTO__((*y));
+91-08-11 switch seterror() to error_info.*
+ add pp:linefile to force file name in line sync
+ add pp:spaceout for probed compilers that don't allow pp override
+91-06-11 fix ignored -I/usr/include bug
+91-04-11 set SYM_INIT in pp.macref for -U on cmd line
+91-01-31 replace pp:pragma and pp:directive with pp:map
+ replace #assert and #unassert with #define #... and #undef #...
+ #assert and #unassert compatibility retained via pp:map
+ replace -D#directive with -D%directive (because of #assert change)
+ add pp:splicecat for \<newline> #define token paste
+ fix \<newline> bug that added space in COMPATIBILITY quoted strings
+90-12-11 fix #pragma pp:multiple
+90-11-11 generalize handling of non-standard keywords for COMPILE
+ replace pp:identifier/PP_IDENTIFIER with pp:reserved/PP_RESERVED
+ pp*keys* -> ppkey
+ add PP_NOISE
+ (gag) handle msdos paths by changing \ to / and retrying on failure
+ (gag) handle msdos :> operator by pplex() '+' return
+ add #pragma prototyped and ppproto.c for prototype conversion
+ add unsigned long arg to PP_MACREF for hashed macro arity+value
+90-10-11 0f is not a float constant
+ change -I-M to -I-I, file just lists include files to be ignored
+ fix ppprobe for __STDC__==0 hybrids
+ add pp.flags and PP_[a-z0-9]+ for exported state info
+90-10-01 fix standalone ppmacref for directives
+ add `try' to C++ keywords
+ fine tune a few COMPILE error messages
+ privatize pp.h
+90-08-11 use opt_again in cmdargs() option parsers
+ (gag) add pp:macref macro reference pragma to handle CC preprocessors
+ (gag) add pp:spaceout to handle ansi + asm hacks
+90-07-17 remove spaces from macdef line sync (blew sun cc)
+90-06-11 add internal ppsymkey to avoid ppsymbol.value pun for SYM_KEYWORD
+90-05-01 fix catliteral bug of `"..." << ' -> `"..." <='
+90-04-01 fix `ifndef-define-endif' include wrapper test
+90-03-27 add setpreroot() to ppop() [ sleazy but well hidden ]
+90-03-22 pp.macref called for all undef's
+90-03-20 add <prefix>cpp checks to ppprobe
+ add pp:hostdir before pp:include in ppprobe
+ fix PP_HOSTDIR op with no dir arg
+90-03-15 System V CCS compatibility update
+ add PP_ASSERT
+ add -A for PP_ASSERT and -YI,dir for PP_STANDARD
+ add ppincref.c and -H to use it
+ -Xa defines __STDC__ to 0 (gak)
+90-03-09 duplicate macro formals cause level 2 error
+90-03-01 add #(ARGC) for (variadic) macro arg count
+90-02-11 fix line sync number bug in pppush()
+89-12-01 ignore leading = in pragma map for old pragma compatibility
+ check for NEWLINE on first macdef line sync
+89-11-11 add -1 arg to pp.incref -- include skipped
+ STRICT 0x7e-macro is T_INVALID per standard
+89-10-31 put all C keys in ppckeys.c, C++ keys in pppkeys.c
+ add pp:identifier pragma to selectively undo PP_COMPILE keywords
+ add tokop() to ppcontrol to support multi-valued pragmas
+ add #ifndef...#endif include optimization for STRICT
+89-10-27 use REF_NORMAL, REF_IF, REF_UNDEF for pp.macref arg2
+89-10-17 fix c(x)y compatibility pasting bug
+ #line 1 "f" now marks "f" included
+89-10-11 enable -I. during initialization
+89-10-01 inhibit pp:linetype syncs for top level #line directives
+ ----- see HISTORY -----
diff --git a/usr/src/lib/libpp/common/gentab.sh b/usr/src/lib/libpp/common/gentab.sh
new file mode 100644
index 0000000000..0234ce6c93
--- /dev/null
+++ b/usr/src/lib/libpp/common/gentab.sh
@@ -0,0 +1,234 @@
+########################################################################
+# #
+# This software is part of the ast package #
+# Copyright (c) 1986-2007 AT&T Knowledge Ventures #
+# and is licensed under the #
+# Common Public License, Version 1.0 #
+# by AT&T Knowledge Ventures #
+# #
+# A copy of the License is available at #
+# http://www.opensource.org/licenses/cpl1.0.txt #
+# (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) #
+# #
+# Information and Software Systems Research #
+# AT&T Research #
+# Florham Park NJ #
+# #
+# Glenn Fowler <gsf@research.att.com> #
+# #
+########################################################################
+:
+# Glenn Fowler
+# AT&T Bell Laboratories
+#
+# @(#)gentab (gsf@research.att.com) 07/17/94
+#
+# C table generator
+#
+# %flags [ prefix=<prefix> ] [ index=<index> ] [ init=<init> ]
+#
+# %keyword <name> [ prefix=<prefix> ] [ index=<index> ] [ init=<init> ] [ first=<id> ] [ last=<id> ]
+#
+# %sequence [ prefix=<prefix> ] [ index=<index> ] [ init=<init> ]
+#
+
+case `(typeset -u s=a n=0; ((n=n+1)); print $s$n) 2>/dev/null` in
+A1) shell=ksh
+ typeset -u ID
+ typeset -i counter err_line
+ ;;
+*) shell=bsh
+ ;;
+esac
+command=$0
+counter=0
+define=1
+err_line=0
+type=""
+index=""
+first=""
+last=""
+table=1
+while :
+do case $1 in
+ -d) table=0 ;;
+ -t) define=0 ;;
+ *) break ;;
+ esac
+ shift
+done
+case $1 in
+"") err_file=""
+ ;;
+*) exec <$1
+ err_file="\"$1\", "
+ ;;
+esac
+while read line
+do case $shell in
+ ksh) ((err_line=err_line+1)) ;;
+ *) err_line=`expr $err_line + 1` ;;
+ esac
+ set '' $line
+ shift
+ case $1 in
+ [#]*) echo "/*"
+ while :
+ do case $1 in
+ [#]*) shift
+ echo " * $*"
+ read line
+ set '' $line
+ shift
+ ;;
+ *) break
+ ;;
+ esac
+ done
+ echo " */"
+ echo
+ ;;
+ esac
+ eval set '""' $line
+ shift
+ case $1 in
+ "") ;;
+ %flags|%keywords|%sequence)
+ case $define:$last in
+ 1:?*) case $shell in
+ ksh) ((n=counter-1)) ;;
+ *) n=`expr $counter - 1` ;;
+ esac
+ echo "#define $prefix$last $n"
+ ;;
+ esac
+ case $type in
+ %flags|%sequence)
+ if test $define = 1
+ then echo
+ fi
+ ;;
+ %keywords)
+ if test $table = 1
+ then echo " 0, 0"
+ echo "};"
+ echo
+ elif test $define = 1
+ then echo
+ fi
+ ;;
+ esac
+ case $index in
+ ?*) eval $index=$counter ;;
+ esac
+ type=$1
+ shift
+ name=""
+ prefix=""
+ index=""
+ init=""
+ first=""
+ last=""
+ case $type in
+ %keywords)
+ case $1 in
+ "") echo "$command: ${err_file}line $err_line: $type table name omitted" >&2
+ exit 1
+ ;;
+ esac
+ name=$1
+ shift
+ if test $table = 1
+ then echo "$name"'[] ='
+ echo "{"
+ fi
+ ;;
+ esac
+ eval "$@"
+ case $init in
+ "") case $type in
+ %flags|%sequence)
+ init=0
+ ;;
+ *) init=1
+ ;;
+ esac
+ ;;
+ esac
+ case $index in
+ "") counter=$init
+ ;;
+ *) eval value=\$$index
+ case $value in
+ "") counter=$init ;;
+ [0123456789]*) counter=$value ;;
+ esac
+ ;;
+ esac
+ case $define:$first in
+ 1:?*) echo "#define $prefix$first $counter" ;;
+ esac
+ ;;
+ %*) echo "$command: ${err_file}line $err_line: $1: unknown keyword" >&2
+ exit 1
+ ;;
+ *) while :
+ do case $1 in
+ "") break
+ ;;
+ *) case $shell in
+ ksh) ID=${1#[!abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_]} ;;
+ *) ID=`echo $1 | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ | sed 's/^[^ABCDEFGHIJKLMNOPQRSTUVWXYZ_]//'` ;;
+ esac
+ case $type in
+ %flags) if test $define = 1
+ then case $counter in
+ 32) echo "$command: ${err_file}line $err_line: warning: $1: too many flag bits" >&2 ;;
+ 1[56789]|[23][0123456789]) long=L ;;
+ *) long= ;;
+ esac
+ echo "#define $prefix$ID (1$long<<$counter)"
+ fi
+ ;;
+ %keywords)
+ if test $define = 1
+ then echo "#define $prefix$ID $counter"
+ fi
+ if test $table = 1
+ then echo " \"$1\", $prefix$ID,"
+ fi
+ ;;
+ %sequence)
+ if test $define = 1
+ then echo "#define $prefix$ID $counter"
+ fi
+ ;;
+ esac
+ case $shell in
+ ksh) ((counter=counter+1)) ;;
+ *) counter=`expr $counter + 1` ;;
+ esac
+ shift
+ ;;
+ esac
+ done
+ ;;
+ esac
+done
+case $define:$last in
+1:?*) case $shell in
+ ksh) ((n=counter-1)) ;;
+ *) n=`expr $counter - 1` ;;
+ esac
+ echo "#define $prefix$last $n"
+ ;;
+esac
+case $type in
+%keywords)
+ if test $table = 1
+ then echo " 0, 0"
+ echo "};"
+ fi
+ ;;
+esac
+exit 0
diff --git a/usr/src/lib/libpp/common/llib-lpp b/usr/src/lib/libpp/common/llib-lpp
new file mode 100644
index 0000000000..d3df1ce176
--- /dev/null
+++ b/usr/src/lib/libpp/common/llib-lpp
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * lib/libpp/common/llib-lpp
+ *
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include "pp.h"
+
+/* automatically generated data start here */
+extern struct ppglobals pp;
+extern char ppctype[];
+extern int ppargs(char**, int);
+extern void ppcpp(void);
+extern void ppcomment(char*, char*, char*, int);
+extern void* ppcontext(void*, int);
+extern void pperror(int, ...);
+extern void ppincref(char*, char*, int, int);
+extern void ppinput(char*, char*, int);
+extern int pplex(void);
+extern void ppline(int, char*);
+extern void ppmacref(struct ppsymbol*, char*, int, int, unsigned long);
+extern void ppop(int, ...);
+extern void pppragma(char*, char*, char*, char*, int);
+extern int ppprintf(char*, ...);
+extern int ppsync(void);
+/* end of automatically generated data */
diff --git a/usr/src/lib/libpp/common/pp.3 b/usr/src/lib/libpp/common/pp.3
new file mode 100644
index 0000000000..988185bd24
--- /dev/null
+++ b/usr/src/lib/libpp/common/pp.3
@@ -0,0 +1,890 @@
+.fp 5 CW
+.de L \" literal font
+.ft 5
+.if !\\$1 \&\\$1 \\$2 \\$3 \\$4 \\$5 \\$6 \f1
+..
+.de LR
+.}S 5 1 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de RL
+.}S 1 5 \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6"
+..
+.de EX \" start example
+.ta 1i 2i 3i 4i 5i 6i
+.PP
+.RS
+.PD 0
+.ft 5
+.nf
+..
+.de EE \" end example
+.fi
+.ft
+.PD
+.RE
+.PP
+..
+.TH PP 3
+.SH NAME \" @(#)pp.3 (gsf@research.att.com) 04/01/92
+pp \- ANSI C preprocessor library
+.SH SYNOPSIS
+.EX
+:PACKAGE: ast
+#include <pp.h>
+%include "pptokens.yacc
+\-lpp
+.EE
+.SH DESCRIPTION
+The
+.I pp
+library provides a tokenizing implementation of the C language preprocessor
+and supports K&R (Reiser), ANSI and C++ dialects.
+The preprocessor is comprised of 12 public functions,
+a global character class table accessed by macros, and
+a single global struct with 10 public elements.
+.PP
+.I pp
+operates in two modes.
+.I Standalone
+mode is used to implement the traditional standalone C preprocessor.
+.I Tokeinizing
+mode provides a function interface to a stream of preprocessed tokens.
+.I pp
+is by default ANSI; the only default predefined symbols are
+.L __STDC__
+and
+.LR __STDPP__ .
+Dialects (K&R, C++) and local conventions are determined by
+compiler specific
+.IR probe (1)
+information that is included at runtime.
+The
+.I probe
+information can be overridden by providing a file
+.L pp_default.h
+with pragmas and definitions for each compiler implementation.
+This file is usually located in the compiler specific
+default include directory.
+.PP
+Directive, command line argument, option and pragma syntax is described in
+.IR cpp (1).
+.I pp
+specific semantics are described below.
+Most semantic differences with standard or classic implementations are in the
+form of optimizations.
+.PP
+Options and pragmas map to
+.L ppop
+function calls described below.
+For the remaining descriptions,
+``setting \f5ppop(PP_\fP\fIoperation\fP\f5)\fP''
+is a shorthand for calling
+.L ppop
+with the arguments appropriate for
+\f5PP_\fP\fIoperation\fP.
+.PP
+The library interface describes only the public functions and struct elements.
+Static structs and pointers to structs are provided by the library.
+The user should not attempt to allocate structs.
+In particular,
+.L sizeof
+is meaningless for
+.I pp
+supplied structs.
+.PP
+The global struct
+.L pp
+provides readonly information.
+Any changes to
+.L pp
+must be done using the functions described below.
+.L pp
+has the following public elements:
+.TP
+.L "char* version"
+The
+.I pp
+implementaion version string.
+.TP
+.L "char* lineid"
+The current line sync directive name.
+Used for standalone line sync output.
+The default value is the empty string.
+See the
+.L ppline
+function below.
+.TP
+.L "char* outfile"
+The current output file name.
+.TP
+.L "char* pass"
+The pragma pass name for
+.I pp.
+The default value is
+.LR pp .
+.TP
+.L "char* token"
+The string representation for the current input token.
+.TP
+.L "int flags"
+The inclusive or of:
+.RS
+.TP
+.L PP_comment
+Set if
+.L ppop(PP_COMMENT)
+was set.
+.TP
+.L PP_compatibility
+Set if
+.L ppop(PP_COMPATIBILITY)
+was set.
+.TP
+.L PP_linefile
+Set if standalone line syncs require a file argument.
+.TP
+.L PP_linetype
+Set if standalone line syncs require a third argument.
+The third argument is
+.L 1
+for include file push,
+.L 2
+for include file pop and null otherwise.
+.TP
+.L PP_strict
+Set if
+.L ppop(PP_STRICT)
+was set.
+.TP
+.L PP_transition
+Set if
+.L ppop(PP_TRANSITION)
+was set.
+.RE
+.TP
+.L "struct ppdirs* lcldirs"
+The list of directories to be searched for "..." include files.
+If the first directory name is "" then it is replaced by the
+directory of the including file at include time.
+The public elements of
+.L "struct ppdirs"
+are:
+.RS
+.TP
+.L "char* name"
+The directory pathname.
+.TP
+.L "struct ppdirs* next"
+The next directory,
+.L 0
+if it is the last in the list.
+.RE
+.TP
+.L "struct ppdirs* stddirs"
+.L pp.stddirs\->next
+is the list of directories to be searched for <...> include files.
+This list may be
+.LR 0 .
+.TP
+.L "struct ppsymbol* symbol"
+If
+.L ppop(PP_COMPILE)
+was set then
+.L pp.symbol
+points to the symbol table entry for the current identifier token.
+.L pp.symbol
+is undefined for non-identifier tokens.
+Once defined, an identifier will always have the same
+.L ppsymbol
+pointer.
+If
+.L ppop(PP_NOHASH)
+was also set then
+.L pp.symbol
+is defined for macro and keyword tokens and
+.L 0
+for all other identifiers.
+The elements of
+.L "struct ppsymbol"
+are:
+.RS
+.TP
+.L "char* name"
+The identifier name.
+.TP
+.L "int flags"
+The inclusive or of the following flags:
+.PD 0
+.RS
+.TP
+.L SYM_ACTIVE
+Currently being expanded.
+.TP
+.L SYM_BUILTIN
+Builtin macro.
+.TP
+.L SYM_DISABLED
+Macro expansion currently disabled.
+.TP
+.L SYM_FUNCTION
+Function-like macro.
+.TP
+.L SYM_INIT
+Initialization macro.
+.TP
+.L SYM_KEYWORD
+Keyword identifier.
+.TP
+.L SYM_LOADED
+Loaded checkpoint macro.
+.TP
+.L SYM_MULTILINE
+.L #macdef
+macro.
+.TP
+.L SYM_NOEXPAND
+No identifiers in macro body.
+.TP
+.L SYM_PREDEFINED
+Predefined macro.
+.TP
+.L SYM_PREDICATE
+Also a
+.L #assert
+predicate.
+.TP
+.L SYM_READONLY
+Readonly macro.
+.TP
+.L SYM_REDEFINE
+Ok to redefine.
+.TP
+.L SYM_VARIADIC
+Variadic function-like macro.
+.TP
+.L SYM_UNUSED
+First unused symbol flag bit index.
+The bits from
+.L (1<<SYM_UNUSED)
+on are initially unset and may be set by the user.
+.RE
+.PD
+.TP
+.L "struct ppmacro* macro"
+Non-zero if the identifier is a macro.
+.L "int macro\->arity"
+is the number of formal arguments for function-like macros and
+.L "char* macro\->value"
+is the macro definition value, a
+.L 0
+terminated string that may contain internal mark sequences.
+.TP
+.L "char* value"
+Initially set to
+.L 0
+and never modified by
+.IR pp .
+This field may be set by the user.
+.RE
+.TP
+.L "Hash_table_t* symtab"
+The macro and identifier
+.L "struct ppsymbol"
+hash table.
+The
+.IR hash (3)
+routines may be used to examine the table, with the exception that the
+following macros must be used for individual
+.L pp.symtab
+symbol lookup:
+.RS
+.TP
+.L "struct ppsymbol* ppsymget(Hash_table_t* table, char* name)"
+Return the
+.L ppsymbol
+pointer for
+.LR name ,
+0 if
+.L name
+not defined.
+.TP
+.L "struct ppsymbol* ppsymset(Hash_table_t* table, char* name)"
+Return the
+.L ppsymbol
+pointer for
+.LR name .
+If
+.L name
+is not defined then allocate and return a new
+.L ppsymbol
+for it.
+.RE
+.RE
+.PP
+Error messages are reported using
+.IR error (3)
+and the following globals relate to
+.IR pp :
+.TP
+.L "int error_info.errors"
+The level 2 error count.
+Error levels above 2 cause immediate exit.
+If
+.L error_info.errors
+is non-zero then the user program exit status should also be non-zero.
+.TP
+.L "char* error_info.file"
+The current input file name.
+.TP
+.L "int error_info.line"
+The current input line number.
+.TP
+.L "int error_info.trace"
+The debug trace level,
+.L 0
+by default.
+Larger negative numbers produce more trace information.
+Enabled when the user program is linked with the
+.B \-g
+.IR cc (1)
+option.
+.TP
+.L "int error_info.warnings"
+The level 1 error count.
+Warnings do not affect the exit status.
+.PP
+The functions are:
+.TP
+.L "extern int ppargs(char** argv, int last);"
+Passed to
+.IR optjoin (3)
+to parse
+.IR cpp (1)
+style options and arguments.
+The user may also supply application specific option parsers.
+Also handles non-standard options like the sun
+.L \-undef
+and GNU
+.LR \-trigraphs .
+Hello in there, ever here of
+.IR getopt (3)?
+.TP
+.L "extern void ppcpp(void);"
+This is the standalone
+.IR cpp (1)
+entry point.
+.L ppcpp
+consumes all of the input and writes the preprocessed text to the output.
+A single call to
+.L ppcpp
+is equivalent to, but more efficient than:
+.EX
+ ppop(PP_SPACEOUT, 1);
+ while (pplex())
+ ppprintf(" %s", pp.token);
+.EE
+.TP
+.L "extern int ppcomment(char* head, char* comment, char* tail, int line);"
+The default comment handler that passes comments to the output.
+May be used as an argument to
+.LR ppop(PP_COMMENT) ,
+or the user may supply an application specific handler.
+.L head
+is the comment head text,
+.L "/*"
+for C and
+.L "//"
+for C++,
+.L comment
+is the comment body,
+.L tail
+is the comment tail text,
+.L "*/"
+for C and
+.B newline
+for C++, and
+.L line
+is the comment starting line number.
+.TP
+.L "extern void pperror(int level, char* format, ...);"
+Equivalent to
+.IR error (3).
+All
+.I pp
+error and warning messages pass through
+.LR pperror .
+The user may link with an application specific
+.L pperror
+to override the library default.
+.TP
+.L "extern int ppincref(char* parent, char* file, int line, int push);"
+The default include reference handler that outputs
+.L file
+to the standard error.
+May be used as an argument to the
+.LR ppop(PP_INCREF) ,
+or the user may supply an application specific handler.
+.L parent
+is the including file name,
+.L file
+is the current include file name,
+.L line
+is the current line number in
+.LR file ,
+and
+.L push
+is non-zero if
+.L file
+is being pushed or
+.L 0
+if file is being popped.
+.TP
+.L "extern void ppinput(char* buffer, char* file, int line);"
+Pushes the
+.L 0
+terminated
+.L buffer
+on the
+.I pp
+input stack.
+.L file
+is the pseudo file name used in line syncs for
+.L buffer
+and
+.L line
+is the starting line number.
+.TP
+.L "int pplex(void)"
+Returns the token type of the next input token.
+.L pp.token
+and where applicable
+.L pp.symbol
+are updated to refer to the new token.
+The token type constants are defined in
+.L pp.h
+for
+.L #include
+and
+.L pp.yacc
+for
+.IR yacc (1)
+.LR %include .
+The token constant names match
+.LR T_[A-Z_]* ;
+some are encoded by oring with
+.L N_[A-Z_]*
+tokens.
+.sp
+The numeric constant tokens and encodings are:
+.EX
+ T_DOUBLE (N_NUMBER|N_REAL)
+ T_DOUBLE_L (N_NUMBER|N_REAL|N_LONG)
+ T_FLOAT (N_NUMBER|N_REAL|N_FLOAT)
+ T_DECIMAL (N_NUMBER)
+ T_DECIMAL_L (N_NUMBER|N_LONG)
+ T_DECIMAL_U (N_NUMBER|N_UNSIGNED)
+ T_DECIMAL_UL (N_NUMBER|N_UNSIGNED|N_LONG)
+ T_OCTAL (N_NUMBER|N_OCTAL)
+ T_OCTAL_L (N_NUMBER|N_OCTAL|N_LONG)
+ T_OCTAL_U (N_NUMBER|N_OCTAL|N_UNSIGNED)
+ T_OCTAL_UL (N_NUMBER|N_OCTAL|N_UNSIGNED|N_LONG)
+ T_HEXADECIMAL (N_NUMBER|N_HEXADECIMAL)
+ T_HEXADECIMAL_L (N_NUMBER|N_HEXADECIMAL|N_LONG)
+ T_HEXADECIMAL_U (N_NUMBER|N_HEXADECIMAL|N_UNSIGNED)
+ T_HEXADECIMAL_UL (N_NUMBER|N_HEXADECIMAL|N_UNSIGNED|N_LONG)
+.EE
+The normal C tokens are:
+.EX
+ T_ID \fIC identifier\fP
+ T_INVALID \fIinvalid token\fP
+ T_HEADER <..>
+ T_CHARCONST '..'
+ T_WCHARCONST L'..'
+ T_STRING ".."
+ T_WSTRING L".."
+ T_PTRMEM ->
+ T_ADDADD ++
+ T_SUBSUB --
+ T_LSHIFT <<
+ T_RSHIFT >>
+ T_LE <=
+ T_GE >=
+ T_EQ ==
+ T_NE !=
+ T_ANDAND &&
+ T_OROR ||
+ T_MPYEQ *=
+ T_DIVEQ /=
+ T_MODEQ %=
+ T_ADDEQ +=
+ T_SUBEQ -=
+ T_LSHIFTEQ <<=
+ T_RSHIFTEQ >>=
+ T_ANDEQ &=
+ T_XOREQ ^=
+ T_OREQ |=
+ T_TOKCAT ##
+ T_VARIADIC ...
+ T_DOTREF .* [\fIif\fP PP_PLUSPLUS]
+ T_PTRMEMREF ->* [\fIif\fP PP_PLUSPLUS]
+ T_SCOPE :: [\fIif\fP PP_PLUSPLUS]
+ T_UMINUS \fIunary minus\fP
+.EE
+If
+.L ppop(PP_COMPILE)
+was set then the keyword tokens are also defined.
+Compiler differences and dialects are detected by the
+.I pp
+.IR probe (1)
+information, and only the appropriate keywords are enabled.
+The ANSI keyword tokens are:
+.EX
+T_AUTO T_BREAK T_CASE T_CHAR
+T_CONTINUE T_DEFAULT T_DO T_DOUBLE_T
+T_ELSE T_EXTERN T_FLOAT_T T_FOR
+T_GOTO T_IF T_INT T_LONG
+T_REGISTER T_RETURN T_SHORT T_SIZEOF
+T_STATIC T_STRUCT T_SWITCH T_TYPEDEF
+T_UNION T_UNSIGNED T_WHILE T_CONST
+T_ENUM T_SIGNED T_VOID T_VOLATILE
+.EE
+and the C++ keyword tokens are:
+.EX
+T_CATCH T_CLASS T_DELETE T_FRIEND
+T_INLINE T_NEW T_OPERATOR T_OVERLOAD
+T_PRIVATE T_PROTECTED T_PUBLIC T_TEMPLATE
+T_THIS T_THROW T_TRY T_VIRTUAL
+.EE
+In addition,
+.L T_ASM
+is recognized where appropriate.
+Additional keyword tokens
+.L ">= T_KEYWORD"
+may be added using
+.LR ppop(PP_COMPILE) .
+.sp
+Many C implementations show no restraint in adding new keywords; some
+PC compilers have tripled the number of keywords.
+For the most part these new keywords introduce noise constructs that
+can be ignored for standard
+.RI ( reasonable )
+analysis and compilation.
+The noise keywords fall in four syntactic categories that map into the two
+noise keyword tokens
+.L T_NOISE
+and
+.LR T_NOISES .
+For
+.L T_NOISES
+.L pp.token
+points to the entire noise construct, including the offending noise keyword.
+The basic noise keyword categories are:
+.RS
+.TP
+.L T_NOISE
+The simplest noise: a single keyword that is noise in any context and maps to
+.LR T_NOISE .
+.TP
+.L T_X_GROUP
+A noise keyword that precedes an optional grouping construct, either
+.L "(..)"
+or
+.L "{..}"
+and maps to
+.LR T_NOISES .
+.TP
+.L T_X_LINE
+A noise keyword that consumes the remaining tokens in the line
+and maps to
+.LR T_NOISES .
+.TP
+.L T_X_STATEMENT
+A noise keyword that consumes the tokens up to the next
+.L ;
+and maps to
+.LR T_NOISES .
+.RE
+.sp
+If
+.L ppop(PP_NOISE)
+is
+.L "> 0"
+then implementation specific noise constructs are mapped to either
+.L T_NOISE
+or
+.L T_NOISES ,
+otherwise if
+.L ppop(PP_NOISE)
+is
+.L "< 0"
+then noise constructs are completely ignored,
+otherwise the unmapped grouping noise tokens
+.L T_X_.*
+are returned.
+.sp
+Token encodings may be tested by the following macros:
+.RS
+.TP
+.L "int isnumber(int token);"
+Non-zero if
+.L token
+is an integral or floating point numeric constant.
+.TP
+.L "int isinteger(int token);"
+Non-zero if
+.L token
+is an integral numeric constant.
+.TP
+.L "int isreal(int token);"
+Non-zero if
+.L token
+is a floating point numeric constant.
+.TP
+.L "int isassignop(int token);"
+Non-zero if
+.L token
+is a C assignment operator.
+.TP
+.L "int isseparate(int token);"
+Non-zero if
+.L token
+must be separated from other tokens by
+.BR space .
+.TP
+.L "int isnoise(int token);"
+Non-zero if
+.L token
+is a noise keyword.
+.RE
+.TP
+.L "extern int ppline(int line, char* file);"
+The default line sync handler that outputs line sync pragmas for the C compiler
+front end.
+May be used as an argument to
+.LR ppop(PP_LINE) ,
+or the user may supply an application specific handler.
+.L line
+is the line number and
+.L file
+is the file name.
+If
+.L ppop(PP_LINEID)
+was set then the directive
+\fB#\fP \fIlineid line \fP"\fIfile\fP" is output.
+.TP
+.L "extern int ppmacref(struct ppsymbol* symbol, char* file, int line, int type);"
+The default macro reference handler that outputs a macro reference pragmas.
+May be used as an argument to
+.LR ppop(PP_MACREF) ,
+or the user may supply an application specific handler.
+.L symbol
+is the macro
+.L ppsymbol
+pointer,
+.L file
+is the reference file,
+.L line
+is the reference line,
+and if
+.L type
+is non-zero a macro value checksum is also output.
+The pragma syntax is
+\fB#pragma pp:macref\fP "\fIsymbol\->name\fP" \fIline checksum\fP.
+.TP
+.L "int ppop(int op, ...)"
+.L ppop
+is the option control interface.
+.L op
+determines the type(s) of the remaining argument(s).
+Options marked by
+.L "/*INIT*/"
+must be done before
+.LR PP_INIT .
+.RS
+.TP
+.L "(PP_ASSERT, char* string) /*INIT*/"
+.L string
+is asserted as if by
+.LR #assert .
+.TP
+.L "(PP_BUILTIN, char*(*fun)(char* buf, char* name, char* args)) /*INIT*/"
+Installs
+.L fun
+as the unknown builtin macro handler.
+Builtin macros are of the form
+.LR "#(name args)" .
+.L fun
+is called with
+.L name
+set to the unknown builtin macro name and
+.L args
+set to the arguments.
+.L buf
+is a
+.L MAXTOKEN+1
+buffer that can be used for the
+.L fun
+return value.
+.L 0
+should be returned on error.
+.TP
+.L "(PP_COMMENT,void (*fun)(char*head,char*body,char*tail,int line) /*INIT*/"
+.TP
+.L "(PP_COMPATIBILITY, char* string) /*INIT*/"
+.TP
+.L "(PP_COMPILE, char* string) /*INIT*/"
+.TP
+.L "(PP_DEBUG, char* string) /*INIT*/"
+.TP
+.L "(PP_DEFAULT, char* string) /*INIT*/"
+.TP
+.L "(PP_DEFINE, char* string) /*INIT*/"
+.L string
+is defined as if by
+.LR #define .
+.TP
+.L "(PP_DIRECTIVE, char* string) /*INIT*/"
+The directive
+.BI # string
+is executed.
+.TP
+.L "(PP_DONE, char* string) /*INIT*/"
+.TP
+.L "(PP_DUMP, char* string) /*INIT*/"
+.TP
+.L "(PP_FILEDEPS, char* string) /*INIT*/"
+.TP
+.L "(PP_FILENAME, char* string) /*INIT*/"
+.TP
+.L "(PP_HOSTDIR, char* string) /*INIT*/"
+.TP
+.L "(PP_HOSTED, char* string) /*INIT*/"
+.TP
+.L "(PP_ID, char* string) /*INIT*/"
+.TP
+.L "(PP_IGNORE, char* string) /*INIT*/"
+.TP
+.L "(PP_INCLUDE, char* string) /*INIT*/"
+.TP
+.L "(PP_INCREF, char* string) /*INIT*/"
+.TP
+.L "(PP_INIT, char* string) /*INIT*/"
+.TP
+.L "(PP_INPUT, char* string) /*INIT*/"
+.TP
+.L "(PP_LINE, char* string) /*INIT*/"
+.TP
+.L "(PP_LINEFILE, char* string) /*INIT*/"
+.TP
+.L "(PP_LINEID, char* string) /*INIT*/"
+.TP
+.L "(PP_LINETYPE, char* string) /*INIT*/"
+.TP
+.L "(PP_LOCAL, char* string) /*INIT*/"
+.TP
+.L "(PP_MACREF, char* string) /*INIT*/"
+.TP
+.L "(PP_MULTIPLE, char* string) /*INIT*/"
+.TP
+.L "(PP_NOHASH, char* string) /*INIT*/"
+.TP
+.L "(PP_NOID, char* string) /*INIT*/"
+.TP
+.L "(PP_NOISE, char* string) /*INIT*/"
+.TP
+.L "(PP_OPTION, char* string) /*INIT*/"
+The directive
+\fB#pragma pp:\fP\fIstring\fP
+is executed.
+.TP
+.L "(PP_OPTARG, char* string) /*INIT*/"
+.TP
+.L "(PP_OUTPUT, char* string) /*INIT*/"
+.TP
+.L "(PP_PASSNEWLINE, char* string) /*INIT*/"
+.TP
+.L "(PP_PASSTHROUGH, char* string) /*INIT*/"
+.TP
+.L "(PP_PLUSPLUS, char* string) /*INIT*/"
+.TP
+.L "(PP_PRAGMA, char* string) /*INIT*/"
+.TP
+.L "(PP_PREFIX, char* string) /*INIT*/"
+.TP
+.L "(PP_PROBE, char* string) /*INIT*/"
+.TP
+.L "(PP_READ, char* string) /*INIT*/"
+.TP
+.L "(PP_RESERVED, char* string) /*INIT*/"
+.TP
+.L "(PP_SPACEOUT, char* string) /*INIT*/"
+.TP
+.L "(PP_STANDALONE, char* string) /*INIT*/"
+.TP
+.L "(PP_STANDARD, char* string) /*INIT*/"
+.TP
+.L "(PP_STRICT, char* string) /*INIT*/"
+.TP
+.L "(PP_TEST, char* string) /*INIT*/"
+.TP
+.L "(PP_TRUNCATE, char* string) /*INIT*/"
+.TP
+.L "(PP_UNDEF, char* string) /*INIT*/"
+.TP
+.L "(PP_WARN, char* string) /*INIT*/"
+.RE
+.TP
+.L "int pppragma(char* dir, char* pass, char* name, char* value, int nl);"
+The default handler that
+copies unknown directives and pragmas to the output.
+May be used as an argument to
+.LR ppop(PP_PRAGMA) ,
+or the user may supply an application specific handler.
+This function is most often called after directive and pragma mapping.
+Any of the arguments may be
+.LR 0 .
+.L dir
+is the directive name,
+.L pass
+is the pragma pass name,
+.L name
+is the pragma option name,
+.L value
+is the pragma option value, and
+.L nl
+is non-zero
+if a trailing newline is required if the pragma is copied to the output.
+.TP
+.L "int ppprintf(char* format, ...);"
+A
+.IR printf (3)
+interface to the standalone
+.I pp
+output buffer.
+Macros provide limited control over output buffering:
+.L "void ppflushout()"
+flushes the output buffer,
+.L "void ppcheckout()"
+flushes the output buffer if over
+.L PPBUFSIZ
+character are buffered,
+.L "int pppendout()"
+returns the number of pending character in the output buffer, and
+.L "void ppputchar(int c)"
+places the character
+.L c
+in the output buffer.
+.SH CAVEATS
+The ANSI mode is intended to be true to the standard.
+The compatibility mode has been proven in practice, but there are
+surely dark corners of some implementations that may have been omitted.
+.SH "SEE ALSO"
+cc(1), cpp(1), nmake(1), probe(1), yacc(1),
+.br
+ast(3), error(3), hash(3), optjoin(3)
+.SH AUTHOR
+Glenn Fowler
+.br
+(Dennis Ritchie provided the original table driven lexer.)
+.br
+AT&T Bell Laboratories
diff --git a/usr/src/lib/libpp/common/pp.def b/usr/src/lib/libpp/common/pp.def
new file mode 100644
index 0000000000..f2d679f3af
--- /dev/null
+++ b/usr/src/lib/libpp/common/pp.def
@@ -0,0 +1,282 @@
+#
+# list of known old cpp predefined symbols
+#
+# @(#)pp.def (gsf@research.att.com) 2002-11-26
+#
+# symbols will be tested for the common `_' permutations
+# qualifiers may be combinations of
+#
+# architecture cpu architecture
+# dialect C dialect
+# machine bundled package name
+# release system release name
+# source *_SOURCE baggage
+# system default is unix
+# vendor compiler vendor
+#
+ABI_SOURCE :source:
+AES_SOURCE :source:
+AIX :architecture:
+AIX32 :architecture:
+AIX64 :architecture:
+ALL_SOURCE :source:
+AM29000 :architecture:
+AM29K :architecture:
+ANSI_CPP :dialect:
+AOSVS :release:
+APPLE :vendor:
+APPLE_CC :dialect:
+ATT :release:
+ATT4 :release:
+BIG_ENDIAN
+BSD :release:
+BSD_COMPAT :source:
+BSD_TYPES :source:
+CDECL
+CI
+CLASSIFY_TYPE
+COMPACT :architecture:
+COMPILER_VER
+CRAY :machine:
+CRAY1 :machine:
+CRAY2 :machine:
+DATAGENERAL :machine:
+DGUX :release:
+DLL
+DMERT :release:
+DYNAMIC :dialect:
+EXTENSIONS :dialect:
+FreeBSD :release:
+GNUC :dialect:vendor:
+GNUC_MINOR
+GNUG :dialect:vendor:
+HFS :vendor:
+HIGHC
+HOST_MIPS
+HPUX_SOURCE :source:
+HUGE :architecture:
+IBMR2 :architecture:
+ISIS
+LANGUAGE_C :dialect:
+LANGUAGE_CPLUS :dialect:
+LANGUAGE_C_PLUS_PLUS :dialect:
+LARGE :architecture:
+LARGE_M
+LATTICE :vendor:
+LONGLONG :dialect:
+LONG_LONG :dialect:
+M68010 :machine:
+M68020 :machine:
+MACH :release:
+MEDIUM :architecture:
+MIPSEB
+MIPSEL
+MIPS_FPSET
+MIPS_ISA
+MIPS_ISA_MIPS1
+MIPS_ISA_MIPS2
+MIPS_SIM
+MIPS_SIM_ABI16
+MIPS_SIM_ABI32
+MIPS_SZINT
+MIPS_SZLONG
+MIPS_SZPTR
+MODERN_C :dialect:
+MOXIE :release:
+MSC_VER :release:
+MSDOS :system:
+MSNT :system:
+MVS :architecture:
+M_ALPHA :architecture:
+M_BITFIELDS
+M_I186 :architecture:
+M_I286 :architecture:
+M_I386 :architecture:
+M_I8086 :architecture:
+M_I86 :architecture:
+M_I86LM
+M_I86MM
+M_I86SM
+M_IX86 :architecture:
+M_LDATA
+M_LTEXT
+M_MRX000 :architecture:
+M_PPC :architecture:
+M_SDATA
+M_STEXT
+M_SYS3
+M_SYS5
+M_SYSIII
+M_SYSV
+M_WDSWAP
+M_XENIX
+NATURAL_ALIGNMENT
+NEXT :release:
+NeXT :release:
+ON_SEL
+OSK
+OVERLAY
+PASCAL
+PDP11 :architecture:
+POSIX
+POSIX2_SOURCE :source:
+POSIX_C_SOURCE :source:
+POSIX_SOURCE :source:
+POWER :architecture:
+PTRDIFF_TYPE
+PWB
+RES
+RT
+SGI_MP_SOURCE :source:
+SGI_REENTRANT_FUNCTIONS :dialect:
+SGI_SOURCE :source:
+SIZE_TYPE
+SMALL :architecture:
+SMALL_M
+STDC_HOSTED
+STDC_IEC_559
+STDC_IEC_559_COMPLEX
+STDC_ISO_10646
+STDC_VERSION
+STD_INCLUDE_DIR
+SVR3
+SVR4
+SVR4_SOURCE :source:
+SYSTYPE_BSD
+SYSTYPE_SVR4
+SYSTYPE_SYSV
+TARGET_LIB
+TINY :architecture:
+TM_DPS6
+TM_L66
+TS
+TS_GCOS
+TS_MOD400
+TURBOC
+UTS :release:
+UWIN :release:
+V9 :release:
+VAX :architecture:
+VAX11C :vendor:
+VAXC :vendor:
+VMS :system:
+WCHAR_TYPE
+WIN32 :release:
+X86 :architecture:
+XOPEN_SOURCE :source:
+XPG2 :source:
+XPG3 :source:
+XPG4 :source:
+_50SERIES
+alliant :machine:
+aosvs :release:
+apollo :machine:
+c_plusplus :dialect:
+cpc :machine:
+cplusplus :dialect:
+cpm :system:
+cpm68k :machine:
+cpm80 :machine:
+cpm86 :machine:
+cray :machine:
+datageneral :machine:
+decus
+dgux :release:
+dmert :release:
+fpcc
+ftx
+gcos :release:
+gimpel :release:
+gnu
+gould :machine:
+hobbit :architecture:
+host_mips
+hp9000s200 :architecture:
+hp9000s300 :architecture:
+hp9000s500 :architecture:
+hp9000s700 :architecture:
+hp9000s800 :architecture:
+hppa :architecture:machine:
+hpux :release:
+i286 :architecture:
+i386 :architecture:
+i80186 :architecture:
+i80286 :architecture:
+i8080 :architecture:
+i8086 :architecture:
+i860 :architecture:
+iAPX286 :architecture:
+iAPX386 :architecture:
+ibm :architecture:
+ibm032 :architecture:
+interdata :architecture:
+kl10
+linux :release:
+m68000 :architecture:
+m68k :architecture:
+m88000 :architecture:
+m88k :architecture:
+mbb
+mc300 :architecture:
+mc500 :architecture:
+mc68000 :architecture:
+mc68008 :architecture:
+mc68010 :architecture:
+mc68020 :architecture:
+mc68k32 :architecture:
+mc700 :architecture:
+mert :release:
+mips :architecture:
+mpm
+msdos :system:
+n16 :architecture:
+n32032 :architecture:
+n32332 :architecture:
+news800
+nomacarg
+nonstopux :system:
+ns1600 :architecture:
+ns16000 :architecture:
+ns32000 :architecture:
+orion :release:
+os :release:
+pcdos :system:
+pdp11 :architecture:
+ppc :architecture:
+pyr :architecture:
+rsx :release:
+sel :architecture:
+selport
+sequent :machine:
+sequoia :machine:
+sparc :architecture:
+spectrum :machine:
+sun :machine:
+sun2 :machine:
+sun3 :machine:
+svr4 :release:
+tahoe :architecture:
+topix :release:
+tops20 :machine:
+tss :system:
+u370 :architecture:
+u3b :architecture:
+u3b15 :architecture:
+u3b2 :architecture:
+u3b20 :architecture:
+u3b200 :architecture:
+u3b20d :architecture:
+u3b4000 :architecture:
+u3b5 :architecture:
+univac :machine:
+unix :system:
+unixpc :machine:
+uts :release:
+vax :architecture:
+vax11c :vendor:
+vaxc :vendor:
+vms :system:
+xinu :release:
+z80 :architecture:
+z800 :architecture:
+z8000 :architecture:
diff --git a/usr/src/lib/libpp/common/pp.h b/usr/src/lib/libpp/common/pp.h
new file mode 100644
index 0000000000..2b91c8e435
--- /dev/null
+++ b/usr/src/lib/libpp/common/pp.h
@@ -0,0 +1,452 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor library public definitions
+ */
+
+#ifndef _PP_H
+#define _PP_H
+
+#ifdef ppsymbol
+/*
+ * undo old nmake cpp name-space intrusion
+ * this disables __LINE__, __FILE__, __DATE__ and __TIME__
+ */
+#undef ppsymbol
+#undef __LINE__
+#define __LINE__ 0
+#undef __FILE__
+#define __FILE__ "libpp"
+#undef __DATE__
+#define __DATE__ "MMM DD YYYY"
+#undef __TIME__
+#define __TIME__ "HH:MM:SS"
+#endif
+
+
+#if PROTOMAIN
+#define HASH_HEADER int hash_header
+#define Hash_table_t char
+#define Sfio_t char
+#define CC_bel (('A'==0301)?0057:0007)
+#define CC_esc (('A'==0301)?0047:0033)
+#define CC_vt 0013
+#else
+#include <limits.h>
+#include <hash.h>
+#include <error.h>
+#include <ccode.h>
+#endif
+
+#define PPDEFAULT "pp_default.h" /* runtime definitions */
+#define PPPROBE "cc" /* default probe key */
+#define PPSTANDARD "/usr/include" /* standard include dir */
+
+#define PPBLKSIZ 1024 /* unit block size */
+#define PPBAKSIZ (1*PPBLKSIZ) /* input pushback size */
+#define PPBUFSIZ (32*PPBLKSIZ) /* io buffer size */
+#define PPTOKSIZ ((PPBUFSIZ/2)-1) /* max token size */
+
+#define PPWRITE(n) do{if(write(1,pp.outbuf,n)!=(n))pperror(ERROR_SYSTEM|3,"%s: write error",pp.outfile);pp.offset+=(n);pp.lastout=pp.outbuf[n-1];}while(0)
+
+#define pplastout() ((pp.outp>pp.outbuf)?*(pp.outp-1):pp.lastout)
+#define ppoffset() (pp.offset+pppendout())
+#define pppendout() (pp.outp-pp.outbuf)
+#define ppputchar(c) (*pp.outp++=(c))
+#define ppflushout() do{if(pp.outp>pp.outbuf){PPWRITE(pp.outp-pp.outbuf);pp.outp=pp.outbuf;}}while(0)
+#define ppcheckout() do{if(pp.outp>pp.oute){PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,pp.oute,pp.outp-pp.oute);pp.oute-=PPBUFSIZ;pp.outp-=2*PPBUFSIZ;}}}while(0)
+
+#define ppsymget(t,n) (struct ppsymbol*)hashlook(t,n,HASH_LOOKUP,NiL)
+#define ppsymref(t,n) (struct ppsymbol*)hashlook(t,n,pp.truncate?HASH_LOOKUP:HASH_LOOKUP|HASH_INTERNAL,NiL)
+#define ppsymset(t,n) (struct ppsymbol*)hashlook(t,n,HASH_CREATE|HASH_SIZE(sizeof(struct ppsymbol)),NiL)
+
+#if CHAR_MIN < 0
+#define pptype (ppctype-(CHAR_MIN)+1)
+#else
+#define pptype (ppctype)
+#endif
+
+#define C_ID (1<<0)
+#define C_DIG (1<<1)
+#define C_SPLICE (1<<2)
+
+#define ppisdig(c) ((pptype)[c]&C_DIG)
+#define ppisid(c) ((pptype)[c]&C_ID)
+#define ppisidig(c) ((pptype)[c]&(C_ID|C_DIG))
+#define ppismac(c) ((pptype)[c]&(C_ID|C_DIG|C_SPLICE))
+#define ppissplice(c) ((pptype)[c]&C_SPLICE)
+
+#define setid(c) ((pptype)[c]|=C_ID)
+#define clrid(c) ((pptype)[c]&=~C_ID)
+#define setdig(c) ((pptype)[c]|=C_DIG)
+#define setsplice(c) ((pptype)[c]|=C_SPLICE)
+
+#define REF_CREATE (REF_NORMAL+1) /* include wrapper (internal) */
+#define REF_DELETE (REF_NORMAL+2) /* macro definition (internal) */
+#define REF_NORMAL 0 /* normal macro reference */
+#define REF_IF (-1) /* if, ifdef, ifndef, elif */
+#define REF_UNDEF (-2) /* undef */
+
+#define SYM_ACTIVE (1L<<0) /* active macro lock */
+#define SYM_BUILTIN (1L<<1) /* builtin macro */
+#define SYM_DISABLED (1L<<2) /* macro expansion disabled */
+#define SYM_EMPTY (1L<<3) /* allow empty/missing actuals */
+#define SYM_FINAL (1L<<4) /* final hosted value */
+#define SYM_FUNCTION (1L<<5) /* macro with args */
+#define SYM_INIT (1L<<6) /* initialization macro */
+#define SYM_INITIAL (1L<<7) /* initial hosted value */
+#define SYM_KEYWORD (1L<<8) /* keyword identifier */
+#define SYM_LEX (1L<<9) /* ppsymkey with lex field */
+#define SYM_MULTILINE (1L<<10) /* multi-line macro */
+#define SYM_NOEXPAND (1L<<11) /* no identifiers in macro body */
+#define SYM_NOTICED (1L<<12) /* symbol noticed in output */
+#define SYM_PREDEFINED (1L<<13) /* predefined macro */
+#define SYM_PREDICATE (1L<<14) /* also a predicate */
+#define SYM_READONLY (1L<<15) /* readonly macro */
+#define SYM_REDEFINE (1L<<16) /* ok to redefine */
+#define SYM_VARIADIC (1L<<17) /* variadic macro with args */
+#define SYM_UNUSED 24 /* first unused symbol flag bit */
+
+#define PP_ASSERT 1 /* preassert symbol */
+#define PP_BUILTIN 2 /* #(<id>) handler */
+#define PP_CDIR 3 /* C (vs. C++) file dirs follow */
+#define PP_CHOP 4 /* include prefix chop */
+#define PP_COMMENT 5 /* passed comment handler */
+#define PP_COMPATIBILITY 6 /* old (Reiser) dialect */
+#define PP_COMPILE 7 /* tokenize for front end */
+#define PP_DEBUG 8 /* set debug trace level */
+#define PP_DEFINE 9 /* predefine symbol */
+#define PP_DEFAULT 10 /* read default include files */
+#define PP_DIRECTIVE 11 /* initialization directive */
+#define PP_DONE 12 /* all processing done */
+#define PP_DUMP 13 /* do checkpoint dump */
+#define PP_FILEDEPS 14 /* output file dependencies */
+#define PP_FILENAME 15 /* set input file name */
+#define PP_HOSTDIR 16 /* hosted file dirs follow */
+#define PP_ID 17 /* add to identifier set */
+#define PP_IGNORE 18 /* ignore this include file */
+#define PP_IGNORELIST 19 /* include ignore list file */
+#define PP_INCLUDE 20 /* add dir to include search */
+#define PP_INCREF 21 /* include file push/ret handler*/
+#define PP_INIT 22 /* one time initialization */
+#define PP_INPUT 23 /* set input source file */
+#define PP_KEYARGS 24 /* name=value macro args */
+#define PP_LINE 25 /* line sync handler */
+#define PP_LINEBASE 26 /* base name in line sync */
+#define PP_LINEFILE 27 /* line sync requires file arg */
+#define PP_LINEID 28 /* PP_LINE directive id */
+#define PP_LINETYPE 29 /* # extra line sync type args */
+#define PP_LOCAL 30 /* previous PP_INCLUDE for "" */
+#define PP_MACREF 31 /* macro def/ref handler */
+#define PP_MULTIPLE 32 /* set all files multiple */
+#define PP_NOHASH 33 /* don't hash PP_COMPILE T_ID's */
+#define PP_NOISE 34 /* convert T_X_* to T_NOISE */
+#define PP_OPTION 35 /* set pragma option */
+#define PP_OPTARG 36 /* unknown option arg handler */
+#define PP_OUTPUT 37 /* set output file sink */
+#define PP_PASSTHROUGH 38 /* ppcpp() expands # lines only */
+#define PP_PEDANTIC 39 /* pedantic non-hosted warnings */
+#define PP_PLUSCOMMENT 40 /* enable C++ comments */
+#define PP_PLUSPLUS 41 /* tokenize for C++ */
+#define PP_POOL 42 /* pool for multiple io passes */
+#define PP_PRAGMA 43 /* passed pragma handler */
+#define PP_PRAGMAFLAGS 44 /* global pragma flags */
+#define PP_PROBE 45 /* ppdefault probe key */
+#define PP_QUOTE 46 /* add to quote set */
+#define PP_READ 47 /* include file without output */
+#define PP_REGUARD 48 /* file pop emits guard define */
+#define PP_RESERVED 49 /* COMPILE reserved keyword */
+#define PP_RESET 50 /* reset to initiali predefs */
+#define PP_SPACEOUT 51 /* pplex returns space,newline */
+#define PP_STANDALONE 52 /* standalone preprocessor */
+#define PP_STANDARD 53 /* standard include dir */
+#define PP_STRICT 54 /* strict implementation */
+#define PP_TEST 55 /* enable (undocumented) tests */
+#define PP_TEXT 56 /* include file with output */
+#define PP_TRANSITION 57 /* on COMPATIBILITY boundary */
+#define PP_TRUNCATE 58 /* truncate macro names */
+#define PP_UNDEF 59 /* undef symbol after ppdefault */
+#define PP_VENDOR 60 /* vendor file dirs follow */
+#define PP_WARN 61 /* enable annoying warnings */
+
+#define PP_comment (1<<0) /* PP_COMMENT is set */
+#define PP_compatibility (1<<1) /* PP_COMPATIBILITY is set */
+#define PP_hosted (1<<2) /* current file is hosted */
+#define PP_linebase (1<<3) /* base name in line sync */
+#define PP_linefile (1<<4) /* line sync file arg required */
+#define PP_linehosted (1<<5) /* line sync hosted arg required*/
+#define PP_lineignore (1<<6) /* line sync for ignored file */
+#define PP_linetype (1<<7) /* line sync type arg required */
+#define PP_strict (1<<8) /* PP_STRICT is set */
+#define PP_transition (1<<9) /* PP_TRANSITION is set */
+
+#define PP_deps (1<<0) /* generate header deps */
+#define PP_deps_file (1<<1) /* write deps to separate file */
+#define PP_deps_generated (1<<2) /* missing deps are generated */
+#define PP_deps_local (1<<3) /* only local header deps */
+
+#define PP_sync 0 /* normal line sync */
+#define PP_sync_push '1' /* [3] include file push */
+#define PP_sync_pop '2' /* [3] include file pop */
+#define PP_sync_ignore '3' /* [3] ignored include file */
+#define PP_sync_hosted '3' /* [4] hosted include file */
+
+#define PP_SYNC_PUSH (1<<0) /* pp.incref PP_sync_push type */
+#define PP_SYNC_POP (1<<1) /* pp.incref PP_sync_pop type */
+#define PP_SYNC_IGNORE (1<<2) /* pp.incref PP_sync_ignore type*/
+#define PP_SYNC_HOSTED (1<<3) /* pp.incref PP_sync_hosted type*/
+#define PP_SYNC_INSERT (1<<4) /* pinserted by other means */
+
+/*
+ * numeric modifiers
+ *
+ * NOTE: 0400 is claimed by error in yacc
+ * (N_PP+30) is the largest valid pp token
+ * free tokens start at T_TOKEN
+ */
+
+#define N_PP 0401 /* pp tokens 0401..0437 */
+#define N_NUMBER 0440 /* numbers 0440..0477 */
+#define N_TEST (N_NUMBER|07700)/* number test mask */
+#define N_TOKEN 0500 /* free 0500..07777 */
+#define N_WIDE 1 /* wide quoted constant */
+
+/*
+ * NOTE: preserve the token ranges and encodings for is*(x)
+ */
+
+#define ppisnumber(x) (((x)&N_TEST)==N_NUMBER)
+#define ppisinteger(x) (((x)&(N_TEST|N_REAL))==N_NUMBER)
+#define ppisreal(x) (((x)&(N_TEST|N_REAL))==(N_NUMBER|N_REAL))
+#define ppisassignop(x) (((x)>=T_MPYEQ)&&((x)<=T_OREQ))
+#define ppisseparate(x) (((x)>=N_PP)&&((x)<=T_WSTRING)||((x)>=N_NUMBER)||((x)=='+')||((x)=='-'))
+
+#define N_LONG 0001
+#define N_UNSIGNED 0002 /* if ppisinteger(x) */
+#define N_FLOAT 0002 /* if ppisreal(x) */
+
+#define N_REAL 0004
+#define N_OCTAL 0010
+#define N_HEXADECIMAL 0020
+
+#define N_EXPONENT 010000 /* for lexing only */
+#define N_SIGN 020000 /* for lexing only */
+#define N_TRAILING 040000 /* for lexing only */
+
+#if !defined(T_DOUBLE)
+
+/*
+ * numeric constants
+ */
+
+#define T_DOUBLE (N_NUMBER|N_REAL)
+#define T_DOUBLE_L (N_NUMBER|N_REAL|N_LONG)
+#define T_FLOAT (N_NUMBER|N_REAL|N_FLOAT)
+#define T_DECIMAL (N_NUMBER)
+#define T_DECIMAL_L (N_NUMBER|N_LONG)
+#define T_DECIMAL_U (N_NUMBER|N_UNSIGNED)
+#define T_DECIMAL_UL (N_NUMBER|N_UNSIGNED|N_LONG)
+#define T_OCTAL (N_NUMBER|N_OCTAL)
+#define T_OCTAL_L (N_NUMBER|N_OCTAL|N_LONG)
+#define T_OCTAL_U (N_NUMBER|N_OCTAL|N_UNSIGNED)
+#define T_OCTAL_UL (N_NUMBER|N_OCTAL|N_UNSIGNED|N_LONG)
+#define T_HEXADECIMAL (N_NUMBER|N_HEXADECIMAL)
+#define T_HEXADECIMAL_L (N_NUMBER|N_HEXADECIMAL|N_LONG)
+#define T_HEXADECIMAL_U (N_NUMBER|N_HEXADECIMAL|N_UNSIGNED)
+#define T_HEXADECIMAL_UL (N_NUMBER|N_HEXADECIMAL|N_UNSIGNED|N_LONG)
+#define T_HEXDOUBLE (N_NUMBER|N_HEXADECIMAL|N_REAL)
+#define T_HEXDOUBLE_L (N_NUMBER|N_HEXADECIMAL|N_REAL|N_LONG)
+
+/*
+ * identifier and invalid token
+ */
+
+#define T_ID (N_PP+0)
+#define T_INVALID (N_PP+1)
+
+/*
+ * quoted constants
+ */
+
+#define T_HEADER (N_PP+2) /* <..> */
+#define T_CHARCONST (N_PP+3) /* '..' */
+#define T_WCHARCONST (T_CHARCONST|N_WIDE) /* L'..' */
+#define T_STRING (N_PP+5) /* ".." */
+#define T_WSTRING (T_STRING|N_WIDE) /* L".." */
+
+/*
+ * multichar operators
+ */
+
+#define T_PTRMEM (N_PP+7) /* -> */
+#define T_ADDADD (N_PP+8) /* ++ */
+#define T_SUBSUB (N_PP+9) /* -- */
+#define T_LSHIFT (N_PP+10) /* << */
+#define T_RSHIFT (N_PP+11) /* >> */
+#define T_LE (N_PP+12) /* <= */
+#define T_GE (N_PP+13) /* >= */
+#define T_EQ (N_PP+14) /* == */
+#define T_NE (N_PP+15) /* != */
+#define T_ANDAND (N_PP+16) /* && */
+#define T_OROR (N_PP+17) /* || */
+#define T_MPYEQ (N_PP+18) /* *= */
+#define T_DIVEQ (N_PP+19) /* /= */
+#define T_MODEQ (N_PP+20) /* %= */
+#define T_ADDEQ (N_PP+21) /* += */
+#define T_SUBEQ (N_PP+22) /* -= */
+#define T_LSHIFTEQ (N_PP+23) /* <<= */
+#define T_RSHIFTEQ (N_PP+24) /* >>= */
+#define T_ANDEQ (N_PP+25) /* &= */
+#define T_XOREQ (N_PP+26) /* ^= */
+#define T_OREQ (N_PP+27) /* |= */
+#define T_TOKCAT (N_PP+28) /* ## */
+#define T_VARIADIC (N_PP+29) /* ... */
+
+/*
+ * C++ tokens
+ */
+
+#define T_DOTREF (N_TOKEN+0) /* .* */
+#define T_PTRMEMREF (N_TOKEN+1) /* ->* */
+#define T_SCOPE (N_TOKEN+2) /* :: */
+
+/*
+ * compiler tokens
+ */
+
+#define T_UMINUS (N_TOKEN+3)
+
+#endif
+
+/*
+ * start of free tokens
+ */
+
+#define T_TOKEN (N_TOKEN+4)
+
+struct ppdirs /* directory list */
+{
+ char* name; /* directory name */
+ struct ppdirs* next; /* next in list */
+
+#ifdef _PP_DIRS_PRIVATE_
+ _PP_DIRS_PRIVATE_
+#endif
+
+};
+
+struct ppkeyword /* pp keyword info */
+{
+ char* name; /* keyword name */
+ int value; /* keyword token value */
+};
+
+struct ppmacro /* pp macro info */
+{
+ int arity; /* # formal arguments */
+ char* value; /* definition value */
+
+#ifdef _PP_MACRO_PRIVATE_
+ _PP_MACRO_PRIVATE_
+#endif
+
+};
+
+struct ppsymbol /* pp symbol info */
+{
+ HASH_HEADER; /* hash stuff and symbol name */
+ unsigned long flags; /* SYM_* status */
+ struct ppmacro* macro; /* macro info */
+ void* value; /* value (for other passes) */
+
+#ifdef _PP_SYMBOL_PRIVATE_
+ _PP_SYMBOL_PRIVATE_
+#endif
+
+};
+
+#define _PP_CONTEXT_BASE_ ((char*)&pp.lcldirs)
+
+#define _PP_CONTEXT_PUBLIC_ \
+ struct ppdirs* lcldirs; /* the "..." dir list */ \
+ struct ppdirs* stddirs; /* next is the <...> dir list */ \
+ int flags; /* PP_[a-z]* flags */ \
+ Hash_table_t* symtab; /* macro and id hash table */
+
+struct ppglobals /* globals accessed by pp.* */
+{
+ const char* version; /* version stamp */
+ char* lineid; /* line sync directive id */
+ char* outfile; /* output file name */
+ char* pass; /* pass name */
+ char* token; /* pplex() token name */
+ struct ppsymbol* symbol; /* last symbol if PP_COMPILE */
+
+ /* exposed for the output macros */
+
+ char* outb; /* output buffer base */
+ char* outbuf; /* output buffer */
+ char* outp; /* outbuf pointer */
+ char* oute; /* outbuf end */
+ unsigned long offset; /* output offset */
+
+#ifdef _PP_CONTEXT_PUBLIC_
+ _PP_CONTEXT_PUBLIC_ /* public context */
+#endif
+
+#ifdef _PP_CONTEXT_PRIVATE_
+ _PP_CONTEXT_PRIVATE_ /* library private context */
+#endif
+
+#ifdef _PP_GLOBALS_PRIVATE_
+ _PP_GLOBALS_PRIVATE_ /* library private additions */
+#endif
+
+};
+
+/*
+ * library interface globals
+ */
+
+#define ppctype _pp_ctype
+
+extern struct ppglobals pp;
+extern char ppctype[];
+
+extern int ppargs(char**, int);
+extern void ppcpp(void);
+extern void ppcomment(char*, char*, char*, int);
+extern void* ppcontext(void*, int);
+extern void pperror(int, ...);
+extern void ppincref(char*, char*, int, int);
+extern void ppinput(char*, char*, int);
+extern int pplex(void);
+extern void ppline(int, char*);
+extern void ppmacref(struct ppsymbol*, char*, int, int, unsigned long);
+extern void ppop(int, ...);
+extern void pppragma(char*, char*, char*, char*, int);
+extern int ppprintf(char*, ...);
+extern int ppsync(void);
+
+#endif
diff --git a/usr/src/lib/libpp/common/pp.key b/usr/src/lib/libpp/common/pp.key
new file mode 100644
index 0000000000..36de339f36
--- /dev/null
+++ b/usr/src/lib/libpp/common/pp.key
@@ -0,0 +1,117 @@
+#
+# list of known non-classic keywords
+#
+# @(#)pp.key (AT&T Labs Research) 2000-05-09
+#
+# keyword type alternate comment
+#
+# . either T_<keyword> or T_NOISE
+# GROUP balanced (), optional {} group
+# LINE upto newline
+# STATEMENT upto ;
+# [pre][.[suf]] [pre]<keyword>[suf]
+#
+
+_Bool . . c9x
+_Complex . . c9x
+_Imaginary . . c9x
+__alignof GROUP .__ gnu
+__attribute GROUP .__ gnu
+__extension GROUP .__ gnu
+__null . .__ gnu
+asm GROUP _,__,__.__ common
+const . __,__.__ ansi
+entry . . ancient
+enum . . pcc,ansi
+fortran . _ ancient
+inline . __,__.__ c9x
+int8 . _,__,__.__ common
+int16 . _,__,__.__ common
+int32 . _,__,__.__ common
+int64 . _,__,__.__ common
+restrict . __,__.__ c9x
+signed . __,__.__ ansi
+typeof GROUP __,__.__ gnu
+void . . pcc,ansi
+volatile . __,__.__ ansi
+
+# new C++ keywords -- is any identifier safe?
+
+and . . C++ (no left_parenthesis?)
+and_eq . . C++
+bitand . . C++
+bitor . . C++
+bool . . C++
+catch . . C++
+compl . . C++
+const_cast . . C++
+dynamic_cast . . C++
+explicit . . C++
+false . . C++
+mutable . . C++
+namespace . . C++
+not . . C++
+not_eq . . C++
+or . . C++
+or_eq . . C++
+protected . . C++
+reinterpret_cast . . C++
+static_cast . . C++
+template . . C++
+throw . . C++
+true . . C++
+try . . C++
+typeid . . C++
+using . . C++
+wchar_t . _,__ C++ ughlee and strange
+xor . . C++
+xor_eq . . C++
+
+# these are typically found in pc compilers, but may be in cross compilers
+
+based GROUP _,__ microsoft
+cdecl . _,__ microsoft
+declspec GROUP _,__ microsoft
+except . _,__ microsoft
+export . _,__ microsoft
+far . _,__ microsoft
+fastcall . _,__ microsoft
+finally . _,__ microsoft
+huge . _,__ microsoft
+interrupt . _,__ microsoft
+leave . _,__ microsoft
+loadds . _,__ microsoft
+near . _,__ microsoft
+novtordisp . _,__ microsoft
+oldcall . _,__ microsoft
+pascal . _,__ microsoft
+saveregs . _,__ microsoft
+segment . _,__ microsoft
+segname . _,__ microsoft
+self . _,__ microsoft
+stdcall . _,__ microsoft
+syscall . _,__ microsoft
+try . _,__ microsoft
+
+cs . _,__ turbo
+ds . _,__ turbo
+es . _,__ turbo
+regparam . _,__ turbo
+seg . _,__ turbo
+ss . _,__ turbo
+
+# these must have been a vms edict
+
+align . _,__,__.__ dec
+f_float . _,__,__.__ dec
+g_float . _,__,__.__ dec
+globaldef . _,__,__.__ dec
+globalref . _,__,__.__ dec
+globalvalue . _,__,__.__ dec
+noshare . _,__,__.__ dec
+readonly . _,__,__.__ dec
+s_float . _,__,__.__ dec
+t_float . _,__,__.__ dec
+unaligned . _,__,__.__ dec
+variant_struct . _,__,__.__ dec
+variant_union . _,__,__.__ dec
diff --git a/usr/src/lib/libpp/common/pp.probe b/usr/src/lib/libpp/common/pp.probe
new file mode 100644
index 0000000000..285f23da71
--- /dev/null
+++ b/usr/src/lib/libpp/common/pp.probe
@@ -0,0 +1,1210 @@
+:
+# Glenn Fowler
+# AT&T Research
+#
+# @(#)pp.probe (AT&T Research) 2006-09-05
+#
+# C probe for libpp
+#
+# NOTE: C.probe must be included or .'d here
+#
+
+ppdef=$dir/pp.def
+ppkey=$dir/pp.key
+ppsym=$dir/ppsym
+for f in $ppdef $ppkey $ppsym
+do test -f $f || { echo "$0: $f: not found" >&4; exit 1 ;}
+done
+
+sed -e "/^#/d" -e "s/[ ].*//" < $ppdef > all.pp
+
+system=
+release=
+version=
+architecture=
+cpu=
+model=
+machine=
+
+#
+# path cleanup
+#
+
+for i in stdinclude usrinclude
+do eval o='$'$i
+ v=$o
+ case $v in
+ *//*) v=`echo $v | sed 's,///*,/,g'` ;;
+ esac
+ if (test . -ef "`pwd`")
+ then k=
+ for x in $v
+ do case $x in
+ */../*|*/..)
+ case $x in
+ /*) a=/ ;;
+ *) a= ;;
+ esac
+ IFS=/
+ set '' $x
+ IFS=$ifs
+ r=
+ for d
+ do r="$d $r"
+ done
+ p=
+ g=
+ for d in $r
+ do case $d in
+ ..) g="$g $d" ;;
+ *) case $g in
+ '') case $p in
+ '') p=$d ;;
+ *) p=$d/$p ;;
+ esac
+ ;;
+ *) set $g
+ shift
+ g=$*
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $a in
+ '') for d in $g
+ do p=$d/$p
+ done
+ ;;
+ *) p=$a$p
+ ;;
+ esac
+ case $p in
+ /) continue ;;
+ esac
+ test $x -ef $p && x=$p
+ ;;
+ esac
+ k="$k $x"
+ done
+ set '' $k
+ shift
+ v=$1
+ case $# in
+ 0) ;;
+ *) shift
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ k=
+ for d
+ do for j in $v
+ do test $d -ef $j && continue 2
+ done
+ k="$k $d"
+ done
+ set '' $k
+ case $# in
+ 1) break ;;
+ esac
+ shift
+ v="$v $1"
+ shift
+ done
+ ;;
+ esac
+ fi
+ case $v in
+ $o) ;;
+ *) eval $i='$'v ;;
+ esac
+done
+
+id="::IDENT::`date`::IDENT::"
+echo '#assert test(ok)
+#if #test(ok)
+#else
+(
+#endif' > assert.$src
+echo '#ifdef __BASE_FILE__
+int ok;
+#else
+(
+#endif' > basefile.$src
+cat > catlit1.i <<'!'
+char test[] = "te"
+"st";
+!
+cat > catlit2.i <<'!'
+char test[] = "te\
+st";
+!
+echo '#define g(a,b) a ## b
+volatile int a;
+const int g(x,y)=1;
+extern int c(int);' > compat.$src
+echo > cpp.$src
+echo "#defincl <x.h>" > defincl.$src
+echo 'int a$b;' > dollar.$src
+echo "#eject" > eject.$src
+echo "#if 0
+(
+#else if 1
+int x;
+#else
+(
+#endif" > elseif.$src
+echo "#define _CAT(a,b,c) a##b##c
+#define hdra hdrx
+#define hdr _CAT(<,hdra,.h>)
+#include hdr" > hdra.$src
+echo "#define _XAT(a,b,c) a##b##c
+#define _CAT(a,b,c) _XAT(a,b,c)
+#define hdra hdrx
+#define hdr _CAT(<,hdra,.h>)
+#include hdr" > hdrx.$src
+echo "int f(){return 0;}" > hdrx.h
+echo "#ident \"$id\"" > ident.$src
+echo "#import \"import.h\"" > import.$src
+echo "int aaa;" > import.h
+echo "#include <inc_next.h>" > inc_next.$src
+mkdir inc0 inc1
+echo "#include_next <inc_next.h>" > inc0/inc_next.h
+echo 'char s[] = "INCLUDE_NEXT";' > inc1/inc_next.h
+echo '# 1 "linefile.i"
+
+# 1 "linefile.i"
+
+int i;' > linefile1.i
+echo '# 1 "linefile.i"
+
+# 1
+
+int i;' > linefile2.i
+echo "int i = 0;" > lineid1.i
+echo '# 1 "t.c"
+int i = 0;' > lineid2.i
+echo '# 1 "t.c"
+int i = 0;' > lineid3.$src
+echo "#include <stdio.h>" > linetype.$src
+echo '#include <sys/types.h>
+main()
+{
+ return sizeof(LONGLONG) != 8;
+}' > longlong.$src
+echo '#include "once.h"
+#include "once.h"' > once.$src
+echo '#ifdef once
+allmultiple
+#else
+#define once
+#endif' > once.h
+echo "extern int a,b;int f(){return a + = b;}" > opspace.$src
+echo "int f(){return(0);} // ((" > pluscom.$src
+echo "class x {int n;} m;" > plusplus.$src
+echo > preinc.$src
+echo '// splice \
+(
+int x = 1;' > plusspl.$src
+echo "int stdc_default_value = __STDC__ ;" > stdc.$src
+echo 'char xxx[] = "abc
+(";' > span.$src
+echo '#define g(a,b) a\
+b
+int ab,xy;
+#define xy XY
+char* g(x,y);' > splice.$src
+{
+echo 'int a\ '
+echo 'b = 1;'
+} > splicesp.$src
+echo '#define g(a,b) a/**/b
+int g(x,y)=1;' > trans.$src
+echo '#define m 65
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 65
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 64
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 63
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 62
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 61
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 60
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 59
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 58
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 57
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 56
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 55
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 54
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 53
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 52
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 51
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 50
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 49
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 48
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 47
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 46
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 45
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 44
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 43
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 42
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 41
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 40
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 39
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 38
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 37
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 36
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 35
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 34
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 33
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 32
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 31
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 30
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxxx 29
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxxx 28
+#define xxxxxxxxxxxxxxxxxxxxxxxxxxx 27
+#define xxxxxxxxxxxxxxxxxxxxxxxxxx 26
+#define xxxxxxxxxxxxxxxxxxxxxxxxx 25
+#define xxxxxxxxxxxxxxxxxxxxxxxx 24
+#define xxxxxxxxxxxxxxxxxxxxxxx 23
+#define xxxxxxxxxxxxxxxxxxxxxx 22
+#define xxxxxxxxxxxxxxxxxxxxx 21
+#define xxxxxxxxxxxxxxxxxxxx 20
+#define xxxxxxxxxxxxxxxxxxx 19
+#define xxxxxxxxxxxxxxxxxx 18
+#define xxxxxxxxxxxxxxxxx 17
+#define xxxxxxxxxxxxxxxx 16
+#define xxxxxxxxxxxxxxx 15
+#define xxxxxxxxxxxxxx 14
+#define xxxxxxxxxxxxx 13
+#define xxxxxxxxxxxx 12
+#define xxxxxxxxxxx 11
+#define xxxxxxxxxx 10
+#define xxxxxxxxx 9
+#define xxxxxxxx 8
+#define xxxxxxx 7
+#define xxxxxx 6
+#define xxxxx 5
+#define xxxx 4
+#define xxx 3
+#define xx 2
+#define x 1
+#if xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx != m
+xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+#endif' > truncate.$src
+cat > zeof.c <<'!'
+char* foo = "az";
+!
+
+allmultiple=
+assert=
+basefile=
+compatibility=1
+defincl=
+dollar=
+eject=
+elseif=
+headerexpand=
+headerexpandall=
+hostedtransition=
+ident=
+import=
+include_next=
+linefile=
+lineid=
+linetype=
+nocatliteral=
+opspace=
+pluscom=
+plusplus=
+plussplice=
+redef=
+reguard=
+reserved=
+spaceout=
+splicecat=
+splicespace=
+strict=
+stringspan=
+transition=
+truncate=
+zeof=
+
+$cc -c assert.$src && assert=1
+
+$cc -c basefile.$src && basefile=__BASE_FILE__
+
+if $cc -E defincl.$src
+then case "`$cc -E defincl.$src | grep -c 'defincl'`" in
+ 0) defincl=1 ;;
+ esac
+fi
+
+if $cc -c catlit1.i 2>e
+then if $cc -c catlit2.i 2>f
+ then if test `wc -c < f` -gt `wc -c < e`
+ then nocatliteral=1
+ fi
+ else nocatliteral=1
+ fi
+fi
+
+$cc -c dollar.$src && dollar=1
+
+$cc -c elseif.$src && elseif=1
+
+if $cc -I. -c hdra.$src
+then headerexpandall=1
+elif $cc -I. -c hdrx.$src
+then headerexpand=1
+fi
+
+if $cc -E eject.$src
+then case "`$cc -E eject.$src | grep -c 'eject'`" in
+ 0) eject=1 ;;
+ esac
+fi
+
+$cc -S ident.$src && grep "$id" ident.s && ident=1
+
+{ $cc -E import.$src | grep aaa ;} && import=1
+
+{ $cc -E -Iinc0 -Iinc1 inc_next.$src | grep INCLUDE_NEXT ;} && include_next=1
+
+if $cc -c linefile1.i
+then $cc -c linefile2.i
+ case $? in
+ 0) ;;
+ *) linefile=1 ;;
+ esac
+fi
+
+if $cc -c lineid1.i 2>b
+then $cc -c lineid2.i 2>e
+ c=$?
+else $cc -c lineid3.c 2>e
+ c=$?
+fi
+case $c in
+0) case `wc -l < b` in
+ `wc -l < e`) ;;
+ *) lineid=line ;;
+ esac
+ ;;
+*) lineid=line
+ ;;
+esac
+
+if $cc -E linetype.$src | grep '^[ ]*#[ ]*[0123456789]*[ ]*".*"[ ]*[12]' > linetype
+then if grep '^[ ]*#[ ]*[0123456789]*[ ]*".*"[ ]*[12][ ][ ]*3' linetype
+ then linetype=2
+ else linetype=1
+ fi
+fi
+
+{ $cc -E once.$src | grep allmultiple ;} && allmultiple=1
+
+$cc -c plusplus.$src && plusplus=1
+
+$cc -c span.$src && stringspan=1
+
+$cc -c splice.$src && splicecat=1
+
+$cc -c splicesp.$src && splicespace=1
+
+exec < $ppkey
+while read keyword type alternate comment
+do case $keyword in
+ .) break ;;
+ ""|"#") continue ;;
+ esac
+ case $type in
+ ""|".") type= ;;
+ *) type="=$type" ;;
+ esac
+ for pre in '' _ __
+ do for suf in '' _ __
+ do case $suf in
+ '') sep= ;;
+ *) sep=. ;;
+ esac
+ case ,,$alternate, in
+ *,$pre$sep$suf,*)
+ key=$pre$keyword$suf
+ undef="$undef $key"
+ echo "int f(){
+ int $key = 0;
+ return $key;
+}
+#undef $key
+int g(){
+ int $key = 0;
+ return $key;
+}" > key.$src
+ $cc -c key.$src >/dev/null 2>&1 || reserved="$reserved $key$type"
+ ;;
+ esac
+ done
+ done
+done
+
+$cc -c opspace.$src && opspace=1
+
+case $plusplus in
+"") $cc -c compat.$src && compatibility=
+ $cc -c pluscom.$src && pluscom=1
+ ;;
+esac
+case $plusplus$pluscom in
+?*) $cc -c plusspl.$src || plussplice=1 ;;
+esac
+case $plusplus in
+?*) mkdir reguard
+ cd reguard
+ echo '#include "ptrone.h"
+#include "ptrdef.h"
+int main () { return gt(2,1) + gt(2.0,1.0); }' > ptr.$src
+ echo '#include "ptrone.h"
+template<class T> int gt(T a, T b) { return a > b; }' > ptrdef.$src
+ echo 'template<class T> int gt(T a, T b);' > ptrdef.h
+ echo '/* empty */' > ptrone.h
+ if $cc -E ptr.$src > x.i && $cc x.i
+ then echo '#ifndef _PTRONE_H
+#define _PTRONE_H
+static int xxx;
+#endif' > ptrone.h
+ if $cc -E ptr.$src > x.i && echo "#define _PTRONE_H" >> x.i && $cc x.i
+ then reguard=1
+ fi
+ fi
+ cd ..
+ rm -rf reguard
+ ;;
+esac
+
+stdc=`$cc -E stdc.$src | sed -e '/stdc_default_value/!d' -e 's/.*=[ ]*//' -e 's/[ ]*;.*//'`
+case $stdc in
+0) $cc -c trans.$src && transition=1 ;;
+[0123456789]*) ;;
+*) stdc= ;;
+esac
+
+truncate=`$cc -E truncate.$src | grep '^[ ]*[0123456789]'`
+$cc -c zeof.c || zeof=1
+
+echo "$predef" >> all.pp
+{
+ case $ppopt$ppenv in
+ ?*) ppcmd=cpp
+ ppdir=.
+ eval $ppenv '$'cc -Dmycpp -E '$'ppopt cpp.$src
+ ;;
+ esac
+ eval set x $probe_verbose
+ shift
+ x=
+ for o in "$@"
+ do set x `$cc $o -c cpp.$src 2>&1`
+ while :
+ do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ *[\\/]rm)
+ ;;
+ [\\/]*) case " $x " in
+ *" $1 "*) ;;
+ *) test -x $1 && x="$x $1" ;;
+ esac
+ ;;
+ esac
+ done
+ case $x in
+ ?*) for f in $x
+ do cp $f x && chmod u+w x && strip x && f=x
+ $ppsym < $f
+ done
+ break
+ ;;
+ esac
+ done
+} 3>&- 3>&1 >/dev/null |
+ sed -e '/^ppsymbol$/d' -e '/^.$/d' -e '/^..$/d' -e '/[ABCDEFGHIJKLMNOPQRSTUVWXYZ].*[abcdefghijklmnopqrstuvwxyz]/d' -e '/[abcdefghijklmnopqrstuvwxyz].*[ABCDEFGHIJKLMNOPQRSTUVWXYZ]/d' |
+ cat - all.pp |
+ sort -u |
+ {
+ for i in 0 1 2 3 4 5
+ do echo "struct { char* name; long value; } predef[] = {" > cpp$i.$src
+ done
+ while read sym junk
+ do case $sym in
+ _*) set 0 ${sym}
+ ;;
+ *_) continue
+ ;;
+ [abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]*)
+ set 1 ${sym} 2 _${sym} 3 _${sym}_ 4 __${sym} 5 __${sym}__
+ ;;
+ *) continue
+ ;;
+ esac
+ while :
+ do case $# in
+ 0|1) break ;;
+ esac
+ {
+ echo "#ifdef $2"
+ echo "\"$2\" , (long) $2 -1,"
+ echo "#endif"
+ } >> cpp$1.$src
+ shift
+ shift
+ done
+ done
+ for i in 0 1 2 3 4 5
+ do echo "\"\", 0 };" >> cpp$i.$src
+ done
+ }
+preval="`for i in 0 1 2 3 4 5;do $cc -E cpp$i.$src;done | sed -e '/\".*\".*,.*,/!d' -e 's/[^\"]*\"\\([^\"]*\\)\"[ ]*,[ ]*([ ]*long[ ]*)[ ]*\\(.*\\)[ ]*-[ ]*1[ ]*,[ ]*\$/\\1 \\2 =/g'` `$cc -dM -E stdc.$src | sed -e '/[ ]*#[ ]*define/!d' -e '/\"/d' -e 's/[ ]*#[ ]*define[ ]*\\([abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]*\\)[ ]*\\(.*\\)/\\1 \\2 =/'`"
+
+for i in bufld namei quota reboot utsname vfs
+do echo "#include <sys/$i.h>" > t.$src
+ if $cc -E t.$src
+ then x=1
+ else x=0
+ fi
+ eval sys_$i=$x
+done
+
+case "`grep -c '__STDC__[-0 ]*[=!]=[ ]*0' $usrinclude/stdio.h 2>/dev/null`" in
+0) ;;
+*) hostedtransition=1 ;;
+esac
+
+mapinclude=
+for i in builtins
+do echo "#include <$i.h>" > t.$src
+ if $cc -E t.$src
+ then mapinclude="$mapinclude <$i.h>=\".\""
+ fi
+done
+
+#
+# the payoff
+#
+
+exec >&3
+
+case "$compatibility:$transition:$dollar" in
+::) strict=1 ;;
+esac
+case $version_stamp in
+?*) echo "/* $version_stamp" ;;
+*) echo "/* $cc" ;;
+esac
+echo "*/"
+case $plusplus:$stdc in
+1:?*) preval="$preval = __STDC__ $stdc ="
+ redef="$redef __STDC__"
+ ;;
+esac
+ppbuiltin=0
+set x $preval
+shift
+case $# in
+0) ;;
+*) echo
+ echo "#pragma pp:predefined"
+ predef=
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ m=$1
+ shift
+ case $m in
+ *'('*) i=`echo "$m" | sed 's,(.*,,'` ;;
+ *) i=$m ;;
+ esac
+ predef="$predef
+$i"
+ eval predef_$i=0
+ while :
+ do case $1 in
+ '=') break ;;
+ *) shift ;;
+ esac
+ done
+ while :
+ do case $1 in
+ '=') shift ;;
+ *) break ;;
+ esac
+ done
+ done
+ for i in $undef
+ do case " $redef " in
+ *" $i "*) ;;
+ *) eval predef_$i=3 ;;
+ esac
+ done
+ set $preval
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ m=$1
+ shift
+ case $m in
+ *'('*) i=`echo "$m" | sed 's,(.*,,'` ;;
+ *) i=$m ;;
+ esac
+ case $i in
+ '=') continue ;;
+ esac
+ v=
+ while :
+ do case $1 in
+ '=') break ;;
+ esac
+ v="$v $1"
+ shift
+ done
+ while :
+ do case $1 in
+ '=') shift ;;
+ *) break ;;
+ esac
+ done
+ case $i in
+ __LCC__)strict=2 ;;
+ _*) ;;
+ *) eval j=\$predef_$i
+ case $j in
+ 0) eval predef_$i=1
+ echo "#define $m$v"
+ case $strict in
+ 1) strict= ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ nopredef=0
+ while :
+ do set $preval
+ while :
+ do case $# in
+ 0) break ;;
+ esac
+ m=$1
+ shift
+ case $m in
+ *'('*) i=`echo "$m" | sed 's,(.*,,'` ;;
+ *) i=$m ;;
+ esac
+ v=
+ while :
+ do case $1 in
+ '=') break ;;
+ esac
+ v="$v $1"
+ shift
+ done
+ while :
+ do case $1 in
+ '=') shift ;;
+ *) break ;;
+ esac
+ done
+ case $nopredef in
+ 2) ;;
+ *) case $v in
+ ' '*' '*)
+ nopredef=1
+ continue
+ ;;
+ ' '[0123456789]*|' '"'"*"'"*)
+ ;;
+ *) case $1 in
+ _*) ;;
+ *) nopredef=1
+ continue
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ eval j=\$predef_$i
+ case $j in
+ 0) case $ppbuiltin in
+ 2) echo "#pragma pp:builtin"
+ ppbuiltin=1
+ ;;
+ esac
+ eval predef_$i=2
+ echo "#define $m$v"
+ ;;
+ 1) case $m in
+ $i) eval predef_$i=2
+ eval j=\$predef___${i}__
+ case $j in
+ [12]) ;;
+ *) case $ppbuiltin in
+ 2) echo "#pragma pp:builtin"
+ ppbuiltin=1
+ ;;
+ esac
+ eval predef___${i}__=2
+ echo "#define __${i}__$v"
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+ esac
+ done
+ case $nopredef in
+ 2) break ;;
+ esac
+ echo "#pragma pp:nopredefined"
+ case $nopredef in
+ 0) break ;;
+ esac
+ ppbuiltin=2
+ nopredef=2
+ done
+ ;;
+esac
+case $basefile in
+?*) case $ppbuiltin in
+ 0|2) ppbuiltin=1
+ echo "#pragma pp:builtin"
+ ;;
+ esac
+ echo "#define $basefile #(BASE)"
+ ;;
+esac
+case $ppbuiltin in
+1) echo "#pragma pp:nobuiltin" ;;
+esac
+
+eval set x $probe_longlong
+shift
+x=
+for o in "$@"
+do rm -f longlong.$exe
+ if $cc -DLONGLONG="$o" -o longlong.$exe longlong.$src &&
+ ./longlong.$exe
+ then x=1
+ break
+ fi
+done
+case $x in
+'') eval set x $probe_longlong_t
+ shift
+ for o in "$@"
+ do rm -f longlong.$exe
+ if $cc -DLONGLONG="$o" -o longlong.$exe longlong.$src &&
+ ./longlong.$exe
+ then echo "#define <long long> $o"
+ break
+ fi
+ done
+ ;;
+esac
+
+echo
+for i in `echo "$predef" | sed -e 's/^__*\(.*\)_*\$/\1/' -e '/^[abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyz]*[0123456789][abcdefghijklmnopqrstuvwxyz0123456789]*\$/!d'` `echo "$predef" | sed -e 's/^__*\(.*\)_*\$/\1/' -e '/^[abcdefghijklmnopqrstuvwxyz][abcdefghijklmnopqrstuvwxyz]*\$/!d'`
+do case $i in
+ *ix) ;;
+ *) architecture=$i
+ break
+ ;;
+ esac
+done
+for i in `sed -e '/^#/d' -e '/:architecture:/!d' -e 's/[ ].*//' < $ppdef`
+do eval j="\" \$predef_$i \$predef__${i} \$predef__${i}_ \$predef___${i} \$predef___${i}__ \""
+ case $j in
+ *" 2 "*)architecture=$i
+ break
+ ;;
+ esac
+done
+for i in `sed -e '/^#/d' -e '/:machine:/!d' -e 's/[ ].*//' < $ppdef`
+do eval j="\" \$predef_$i \$predef__${i} \$predef__${i}_ \$predef___${i} \$predef___${i}__ \""
+ case $j in
+ *" 2 "*)machine="$machine $i" ;;
+ esac
+done
+case $sys_bufld$sys_reboot$sys_utsname in
+1??) release=research
+ version=9
+ ;;
+01?) release=bsd
+ case $sys_quota in
+ 0) case $sys_vfs in
+ 0) version=4.1
+ ;;
+ esac
+ ;;
+ 1) case $sys_namei in
+ 0) version=4.2
+ ;;
+ 1) version=4.3
+ ;;
+ esac
+ ;;
+ esac
+ ;;
+001) release=V
+ ;;
+esac
+for i in `sed -e '/^#/d' -e '/:release:/!d' -e 's/[ ].*//' < $ppdef`
+do eval j=\$predef_$i
+ case $j in
+ 2) release="$release $i" ;;
+ esac
+done
+for i in `sed -e '/^#/d' -e '/:system:/!d' -e 's/[ ].*//' < $ppdef`
+do eval j=\$predef_$i
+ case $j in
+ 2) system="$system $i" ;;
+ esac
+done
+case $release in
+topix) release="$release V"
+ ;;
+esac
+case $assert in
+?*) for i in $predef
+ do case $i in
+ _*|*_) ;;
+ *) for p in architecture cpu machine system
+ do echo "#if #$p($i)
+eval \"case \\\" \$$p \\\" in *\\\" $i \\\"*) ;; *) $p=\\\"$i \$$p\\\" ;; esac\"
+: avoid string literal concatenation
+#endif"
+ done
+ ;;
+ esac
+ done > t.$src
+ eval "`$cc -E t.$src`"
+ set x x $prepred
+ while :
+ do shift
+ shift
+ case $# in
+ [01]) break ;;
+ esac
+ eval "
+ case \" \$$1 \" in
+ *\" $2 \"*) ;;
+ *) $1=\"$2 \$$1\" ;;
+ esac
+ "
+ done
+ ;;
+esac
+case $system in
+"") system=unix ;;
+esac
+case $architecture in
+ibm|uts|u370) model=370
+ architecture=ibm
+ ;;
+m*68*) architecture=m68000
+ for i in $predef
+ do case $i in
+ m*68*[123456789][0123456789])
+ model=`echo $i | sed 's/.*\(..\)/\1/'`
+ break
+ ;;
+ esac
+ done
+ ;;
+u3b?*) model=`echo $architecture | sed 's/u3b//'`
+ architecture=3b
+ ;;
+u3b) case $model in
+ "") model=20 ;;
+ esac
+ architecture=3b
+ ;;
+vax[0123456789]*)
+ model=`echo $architecture | sed 's/vax//'`
+ architecture=vax
+ ;;
+hp[0123456789]*s[0123456789])
+ case $release in
+ [abcdefghijklmnopqrstuvwxyz]*.[abcdefghijklmnopqrstuvwxyz]*.*)
+ version=$release
+ release=V
+ ;;
+ esac
+ architecture="$architecture `echo $architecture | sed 's/s.*//'`"
+ ;;
+esac
+case $hosttype in
+*.*) i=`echo $hosttype | sed -e 's,.*\.,,'` ;;
+*) i=$hosttype ;;
+esac
+case $i in
+unknown);;
+?*) case " $architecture " in
+ *" $i "*) ;;
+ *) architecture="$architecture $i" ;;
+ esac
+ ;;
+esac
+case $architecture in
+"") echo "$cc: warning: architecture not determined" >&4
+ set x $machine
+ architecture=$2
+ ;;
+esac
+echo "#define #hosttype($hosttype)"
+for i in $system
+do echo "#define #system($i)"
+done
+case $release in
+"") echo "#define #release()" ;;
+*) for i in $release
+ do echo "#define #release($i)"
+ case $i in
+ V) echo "#define #release(system5)" ;; # compatibility
+ esac
+ done
+ ;;
+esac
+echo "#define #version($version)"
+case $architecture in
+"") echo "#define #architecture()" ;;
+*) for i in `echo $architecture | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ do echo "#define #architecture($i)"
+ done
+ ;;
+esac
+echo "#define #model($model)"
+case $machine in
+"") case $architecture:$model in
+ ?*:?*) set x $architecture; machine="$2/$model $architecture" ;;
+ *) machine=$architecture ;;
+ esac
+ ;;
+*) machine="$machine $architecture"
+ ;;
+esac
+case $machine in
+"") echo "#define #machine()" ;;
+*) j=
+ for i in `echo $machine | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ do case " $i " in
+ *" $j "*)
+ ;;
+ *) j="$j $i"
+ echo "#define #machine($i)"
+ ;;
+ esac
+ done
+ ;;
+esac
+for i in $cpu
+do echo "#define #cpu($i)"
+done
+echo "#define #addressing()"
+for i in $ATTRIBUTES
+do eval d=\$$i
+ n=`echo $i | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ echo "#define #$n($d)"
+done
+case $stdc in
+?*) echo "#define #dialect(ansi)" ;;
+esac
+case $plusplus in
+?*) echo "#define #dialect(C++)" ;;
+esac
+case $hosted in
+"") echo "#define #dialect(cross)" ;;
+esac
+case $so:$dynamic:$static in
+::) ;;
+*) echo "#define #dialect(dynamic)" ;;
+esac
+echo
+case $plusplus in
+?*) echo "#pragma pp:plusplus" ;;
+esac
+case $reserved in
+?*) echo "#pragma pp:reserved" $reserved ;;
+esac
+case $nocatliteral in
+?*) echo "#pragma pp:nocatliteral" ;;
+esac
+case $opspace in
+?*) echo "#pragma pp:opspace" ;;
+esac
+case $pluscom in
+?*) echo "#pragma pp:pluscomment" ;;
+esac
+case $plussplice in
+?*) echo "#pragma pp:plussplice" ;;
+esac
+case $reguard in
+?*) echo "#pragma pp:reguard" ;;
+esac
+case $splicecat in
+?*) echo "#pragma pp:splicecat" ;;
+esac
+case $splicespace in
+?*) echo "#pragma pp:splicespace" ;;
+esac
+case $stringspan in
+?*) echo "#pragma pp:stringspan" ;;
+esac
+case $stdc in
+"") echo "#pragma pp:compatibility"
+ ;;
+0) echo "#pragma pp:transition"
+ ;;
+1) case $strict in
+ ?*) echo "#pragma pp:strict" ;;
+ esac
+ ;;
+esac
+case $hostedtransition in
+1) echo "#pragma pp:hostedtransition" ;;
+esac
+case $stdc in
+?*) case $ppopt$ppenv in
+ "") spaceout=1
+ echo "#pragma pp:spaceout"
+ ;;
+ esac
+ ;;
+esac
+case $truncate in
+?*) echo "#pragma pp:truncate $truncate" ;;
+esac
+case $zeof in
+?*) echo "#pragma pp:zeof" ;;
+esac
+case $dollar in
+1) echo '#pragma pp:id "$"' ;;
+esac
+cdir=-I+C
+hdir=-I+H
+set x $stdinclude
+while :
+do shift
+ case $# in
+ 0) break ;;
+ esac
+ case $1 in
+ $cdir|$hdir)
+ ;;
+ -I+C) cdir=$1
+ echo "#pragma pp:nocdir"
+ ;;
+ -I-C) cdir=$1
+ echo "#pragma pp:cdir"
+ ;;
+ -I+H) hdir=$1
+ echo "#pragma pp:nohostdir"
+ ;;
+ -I-H) hdir=$1
+ echo "#pragma pp:hostdir"
+ ;;
+ -I*) ;;
+ *) echo "#pragma pp:include \"$1\""
+ ;;
+ esac
+done
+case $usrinclude in
+/usr/include)
+ ;;
+?*) echo "#pragma pp:standard \"$usrinclude\""
+ ;;
+esac
+case $plusplus in
+?*) case $usrinclude in
+ ?*) if grep plusplus $usrinclude/ctype.h >/dev/null 2>&1
+ then echo '#pragma pp:nocdir "-"'
+ fi
+ ;;
+ esac
+ ;;
+esac
+case $mapinclude in
+?*) echo "#pragma pp:mapinclude hosted$mapinclude" ;;
+esac
+case $linefile in
+?*) echo "#pragma pp:linefile" ;;
+esac
+case $lineid in
+?*) echo "#pragma pp:lineid line" ;;
+esac
+case $linetype in
+1) echo "#pragma pp:linetype" ;;
+?*) echo "#pragma pp:linetype $linetype" ;;
+esac
+case $allmultiple in
+"") echo "#pragma pp:noallmultiple" ;;
+esac
+case $defincl in
+1) echo '#pragma pp:map "/#(pragma )?defincl>/"' ;;
+esac
+case $eject in
+1) echo '#pragma pp:map "/#(pragma )?eject>/"' ;;
+esac
+case $elseif in
+1) echo "#pragma pp:elseif" ;;
+esac
+case $headerexpand in
+1) echo "#pragma pp:headerexpand" ;;
+esac
+case $headerexpandall in
+1) echo "#pragma pp:headerexpandall" ;;
+esac
+case $ident in
+1) echo '#pragma pp:map "/#(pragma )?ident>/" "/#(pragma )?/###/"' ;;
+*) echo '#pragma pp:map "/#(pragma )?ident>/"' ;;
+esac
+case $import in
+1) echo '#pragma pp:map "/#(pragma )?import>/" "/#(pragma )?import(.*)/__STDPP__IMPORT__(\2)/"
+#macdef __STDPP__IMPORT__(x)
+#pragma pp:noallmultiple
+#include x
+#pragma pp:allmultiple
+#endmac' ;;
+esac
+case $include_next in
+1) echo '#pragma pp:map "/#include_next>/" ",[^\<]*\<,#include <.../,"' ;;
+esac
+echo '#pragma pp:map "/#pragma lint:/" ",#pragma lint:(.*),##/*\1*/,u"'
+echo '#pragma pp:map "/#(pragma )?sccs>/"'
+
+case $stdc:$spaceout in
+1:) case ' '$reserved' ' in
+ *' 'asm' '*|*' 'asm=*)
+ echo "#macdef asm"
+ echo "#pragma pp:spaceout"
+ echo "#undef asm"
+ echo "asm"
+ echo "#endmac"
+ ;;
+ esac
+ ;;
+esac
+
+if $cc -E preinc.$src > preinc.out
+then for f in `sed -e 's,\\\\,/,g' -e 's,"[ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz]:/,"/,g' -e '/^#[line ]*[0123456789][0123456789]*[ ][ ]*"[\\/]/!d' -e 's/^#[line ]*[0123456789][0123456789]*[ ][ ]*".*[\\/]\(.*\)".*/\1/' preinc.out | sort -u`
+ do case $f in
+ *preinc.$src*)
+ ;;
+ *) echo "#include <$f>"
+ ;;
+ esac
+ done
+fi
diff --git a/usr/src/lib/libpp/common/pp.tab b/usr/src/lib/libpp/common/pp.tab
new file mode 100644
index 0000000000..30a576d404
--- /dev/null
+++ b/usr/src/lib/libpp/common/pp.tab
@@ -0,0 +1,233 @@
+#
+# Glenn Fowler
+# AT&T Research
+#
+# @(#)pp.tab (AT&T Labs Research) 2006-05-09
+#
+# C preprocessor tables and states
+#
+# + marks extensions to the standard
+#
+
+%keywords "static struct ppkeyword directives"
+
+ define
+ elif
+ else
+ endif
+ +endmac
+ error
+ if
+ ifdef
+ ifndef
+ include
+ +let
+ line
+ +macdef
+ pragma
+ +rename
+ undef
+ +warning
+
+%keywords "static struct ppkeyword options" prefix=X_ index=optindex last=last_option
+
+ allmultiple
+ allpossible
+ builtin
+ catliteral
+ cdir
+ checkpoint
+ chop
+ compatibility
+ debug
+ elseif
+ externalize
+ final
+ hide
+ headerexpand
+ headerexpandall
+ hosted
+ hostedtransition
+ hostdir
+ id
+ ignore
+ include
+ initial
+ keyargs
+ line
+ linebase
+ linefile
+ lineid
+ linetype
+ macref
+ map
+ mapinclude
+ modern
+ multiple
+ native
+ note
+ opspace
+ passthrough
+ pedantic
+ pluscomment
+ plusplus
+ plussplice
+ pragmaflags
+ pragmaexpand
+ predefined
+ prefix
+ preserve
+ proto
+ prototyped
+ quote
+ readonly
+ reguard
+ reserved
+ spaceout
+ splicecat
+ splicespace
+ standard
+ statement
+ strict
+ stringspan
+ stringsplit
+ system_header
+ test
+ text
+ transition
+ truncate
+ vendor
+ version
+ warn
+ zeof
+
+%keywords "static struct ppkeyword predicates" prefix=X_ index=optindex
+
+ defined
+ +exists
+ +included
+ +match
+ +noticed
+ +option
+ sizeof
+ +strcmp
+
+%keywords "static struct ppkeyword readonlys" prefix=R_
+
+ defined
+
+%flags # state : coupled, high frequency
+
+ ADD # add pp.addbuf into output buffer
+ COLLECTING # collecting macro call arguments
+ COMPATIBILITY # compatibility (Reiser) dialect
+ COMPILE # tokenize for compiler
+ CONDITIONAL # processing #[el]if directive
+ DEFINITION # processing macro definition
+ DIRECTIVE # processing directive
+ DISABLE # disable macro evaluation
+ EOF2NL # pass eof as newline token
+ ESCAPE # \ -> \\ in QUOTE|SQUOTE
+ FILEPOP # 0 on IN_FILE pop - no popin
+ HEADER # processing include statement
+ HIDDEN # hidden lines encountered
+ JOINING # joining adjacent strings
+ NEWLINE # last non-space was newline
+ NOEXPAND # no macro expansions or disables
+ NOSPACE # don't pass space+ as token
+ NOTEXT # don't output text
+ NOVERTICAL # vertical space invalid
+ PASSEOF # pass EOF as 0 without pop
+ PASSTHROUGH # ppcpp expands # lines only
+ QUOTE # processing "..." token
+ SKIPCONTROL # skip until # control or EOF
+ SKIPMACRO # disable next macro
+ SPACEOUT # output spaces in STANDALONE
+ SQUOTE # processing '...' token
+ STANDALONE # output tokens on stdout
+ STRICT # strict implementation
+ STRIP # strip quotes from T_STRING and T_CHARCONST
+ SYNCLINE # output line sync soon
+ TRANSITION # on the COMPATIBILITY boundary
+ WARN # note obnoxious incompatibilities
+
+%flags # mode : coupled, low frequency
+
+ ALLMULTIPLE # all files can be included more than once
+ BUILTIN # mark macro definitions builtin
+ CATLITERAL # concatenate adjacent "..."
+ DUMP # do a checkpoint dump
+ EXPOSE # expose hidden macros
+ EXTERNALIZE # set PROTO_EXTERNALIZE
+ FILEDEPS # output file dependencies
+ GENDEPS # missings FILEDEPS are generated
+ HEADERDEPS # <...> too for FILEDEPS
+ HOSTED # hosted include file
+ HOSTEDTRANSITION # hosted include files get __STDC__=0
+ INACTIVE # inactive conditional branch
+ INIT # initialization phase
+ LOADING # loading a checkpoint file
+ MARKC # last ppsearch() file was in C language
+ MARKHOSTED # last ppsearch() file was hosted
+ MARKMACRO # mark macro to disable later
+ PEDANTIC # pedantic non-hosted non-standard warnings
+ READONLY # mark macro definitions readonly
+ RELAX # relax complaints for this directive
+
+%flags # options : uncoupled, low frequency
+
+ ALLPOSSIBLE # ignore top level conditionals
+ DEFINITIONS # output macro definitions
+ ELSEIF # #else if|ifdef|ifndef ok
+ FINAL # final hosted macro value
+ HEADEREXPAND # HEADEREXPANDALL but macro args not expanded
+ HEADEREXPANDALL # expanded < does not quote #include macros
+ IGNORELINE # ignore #line until first file arg
+ INITIAL # initial hosted macro value
+ KEEPNOTEXT # keep NOTEXT setting
+ KEYARGS # name=value macro arguments
+ MODERN # generate modern output (\a instead of \007)
+ NATIVE # report native paths
+ NOHASH # don't hash PP_COMPILE T_ID's
+ NOISE # convert T_X_* to T_NOISES
+ NOISEFILTER # filter (ignore) NOISE
+ NOPROTO # disable ppproto()
+ PLUSCOMMENT # enable C++ comments
+ PLUSPLUS # preprocess for C++
+ PLUSSPLICE # C++ // \<newline> does not splice
+ PRAGMAEXPAND # expand #pragma args
+ PREDEFINED # mark macro definitions predefined
+ PREDEFINITIONS # output predefined macro definitions
+ PREFIX # prefix include for compatibility
+ PRESERVE # preserve input layout
+ PROTOTYPED # force all input to be prototyped
+ REGUARD # emit header guard define at file pop
+ SPLICECAT # \<newline> ok for COMPATIBILITY catenation
+ SPLICESPACE # \<space>+<newline> == \<newline> for jcl
+ STRINGSPAN # <newline> in string ok
+ STRINGSPLIT # "...\\n..." => "..."\n"..."
+ TRUNCATE # truncate identifiers
+ ZEOF # ^Z anywhere in file => EOF
+
+%keywords "static struct ppkeyword variables" prefix=V_ index=optindex
+
+ _Pragma
+ +ARGC
+ +BASE
+ DATE
+ FILE
+ +FUNCTION
+ LINE
+ +PATH
+ +SOURCE
+ -STDC
+ TIME
+ +VERSION
+ -default
+ -directive
+ -empty
+ -getenv
+ -getmac
+ -getopt
+ -getprd
+ -iterate
diff --git a/usr/src/lib/libpp/common/ppargs.c b/usr/src/lib/libpp/common/ppargs.c
new file mode 100644
index 0000000000..0aaff3905e
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppargs.c
@@ -0,0 +1,603 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common preprocessor command line argument parse
+ * called by optjoin()
+ */
+
+static const char usage[] =
+"[-?\n@(#)$Id: cpp (AT&T Research) 2006-01-11 $\n]"
+USAGE_LICENSE
+"[+NAME?cpp - C language preprocessor]"
+"[+DESCRIPTION?\bcpp\b is the preprocessor for all C language dialects. It is"
+" a standalone version of the \blibpp\b(3) preprocessor library. The"
+" C dialect implemented by \bcpp\b is determined by probing \bcc\b(1)"
+" using \bprobe\b(1). The path of the emulated compiler can be changed"
+" by the \b-D-X\b command line option.]"
+"[+?If \aoutput\a is omitted then the standard output is written; if \ainput\a"
+" is also omitted then the standard input is read. NOTE: this is an"
+" ancient, non-standard, non-intuitiive file operand syntax that is"
+" required by \bcc\b(1); use shell file name expansion at your peril.]"
+"[+?\bcpp\b specific options are set by the \b-D-\b and \b-I-\b options.]"
+
+"[C:comments?Pass comments to the output. By default comments are omitted.]"
+"[D:define?Define the macro \aname\a to have \avalue\a; \b1\b is assumed if"
+" \b=\b\avalue\a is omitted. If \aname\a begins with \b:\b then it is"
+" interpreted as a \blibpp\b(3) \b#pragma pp:\b statement; if \aname\a"
+" begins with \b%\b then it is interpreted as a \blibpp\b(3) \b#\b"
+" directive statement; if \aname\a begins with \b-\b or \b+\b then it is"
+" interpreted as a \blibpp\b(3) option; \b-\b turns the option on,"
+" \b+\b turns it off. Most options have a \b#pragma\b counterpart that"
+" is listed with the option definition. Right, this is ugly, but its the"
+" only portable way to pass options through \bcc\b(1) to"
+" \bcpp\b:]:[name[=value]]]{"
+" [+-D-C, pp::compatibility?Preprocess for K&R compatibility.]"
+" [+-D-D\alevel\a, \bpp::debug\b \alevel\a?Set the debug trace level."
+" Higher levels produce more output. Levels higher than 3"
+" enabled only in \b-g\b compiled versions.]"
+" [+-D-F\aname\a?Set the main input file name to \aname\a. This only"
+" affects error message and line sync output.]"
+" [+-D-H, pp::hosted?All directories are hosted; compatibility"
+" warning messages from hosted directory headers are suppressed.]"
+" [+-D-I, pp::cdir?All directories contain C headers; used only with"
+" \b-D-+\b.]"
+" [+-D-K, pp::keyargs?Enable the non-standard \aname=value\a macro"
+" argument mode.]"
+" [+-D-L\b[\aid\a]], \bpp::lineid\b [\aid\a]]?Set the line sync directive"
+" id to \aid\a or null if omitted.]"
+" [+-D-M, pp::nomultiple?Disable multiple include detection.]"
+" [+-D-P, pp::passthrough?Enable the non-standard passthrough mode; may"
+" be useful for processing non-C input.]"
+" [+-D-Q, pp::dump?Dump macro definitions to the output so that the"
+" output may be passed through \bcpp\b again. Used for"
+" generating precompiled headers.]"
+" [+-D-R, pp::transition?Enable the transition preprocessing mode. Used"
+" for compilers that can't make up their semantics between"
+" K&R and ISO.]"
+" [+-D-S, pp::strict?Enable strict preprocessing semantics and warnings."
+" Works with any mode (compatibiliy, transition,"
+" or the default ISO).]"
+" [+-D-T\atest\a, \bpp::test\b \atest\a?Enable implementation specific"
+" test code according to \atest\a.]"
+" [+-D-W, pp::warn?Enable pedantic warnings in non-hosted files.]"
+" [+-D-X\b[\acc\a]]?Preprocess for the compiler \acc\a which must be"
+" an executable path or an executable on \b$PATH\b.]"
+" [+-D-Z, pp::pool?Enable pool mode. See \blibpp\b(3).]"
+" [+-D-d?List canonicalized \b#define\b statements for non-predefined"
+" macros in the output. ]"
+" [+-D-m?List canonicalized \b#define\b statements for all macros. All"
+" other output is disabled.]"
+" [+-D-+, pp::plusplus?Preprocess for the C++ dialect.]"
+"}"
+"[I:include?Append \adirectory\a to the list of directories searched for"
+" \b#include\b files. If \adirectory\a is \b-\b then: (1) \b-I\b"
+" directories before \b-I-\b are searched only for \"...\" include"
+" files; (2) \b-I\b directories after \b-I-\b are searched for"
+" \"...\" and <...> include files; (3) the directory \b.\b is searched"
+" only if it is explicitly specified by a \b-I\b option.]:?[directory]{"
+" [+-I-C\adirectory\a, \bpp::cdir\b \adirectory\a?Mark \adirectory\a"
+" as a C header directory. Used with \bpp:plusplus\b.]"
+" [+-I-D[\afile\a]]?Read the default \bprobe\b(1) definitions from"
+" \afile\a, or ignore the default definitions if \afile\a"
+" is omitted.]"
+" [+-I-H\adirectory\a, \bpp::hostdir\b \adirectory\a?Mark \adirectory\a"
+" as a hosted directory. Headers from hosted directories have"
+" compatibility warnings disabled.]"
+" [+-I-I\aheader\a, \bpp::ignore\b \aheader\a?Add \aheader\a to the"
+" list of ignored headers.]"
+" [+-I-M\afile\a?\afile\a contains a sequence of \aheader\a"
+" [= \"\amap\a\" ]] lines, where \aheader\a is either <\aname\a>"
+" or \"\aname\a\", and \"\amap\a\" is an explicit binding"
+" for \aheader\a. \aheader\a is ignored if = \"\amap\a\" is"
+" omitted.]"
+" [+-I-R\afile\a?Include \afile\a but do not emit text or line syncs.]"
+" [+-I-S\adirectory\a?Add \adirectory\a to the default standard include"
+" directory list.]"
+" [+-I-T\afile\a?Include \afile\a and emit text to the output file.]"
+"}"
+"[M:dependencies?Generate \bmake\b(1) dependencies. Not needed with"
+" \bnmake\b(1). \b-M\b may be followed by optional \aflags\a to change"
+" dependency output styles:]{"
+" [+D?Generate dependencies in a separate \b.d\b file. Preprocessed"
+" output is still written to \aoutput\a, or the standard output"
+" if \aoutput\a is omitted.]"
+" [+G?Generate missing dependencies too.]"
+" [+M?Only generate local header dependencies; \ahosted\a headers are"
+" omitted. Note that \ahosted\a headers are determined by"
+" \b-I-H\b and the \bpp:hosted\b and \bpp:hostdir\b pragmas;"
+" no special distiction is made between \"\" and <> \binclude\b"
+" styles.]"
+"}"
+"[P!:sync?Emit line syncs.]"
+"[U:undefine?Remove the definition for the macro \aname\a.]:[name]"
+
+"[A:assert?Enter the assertion via \b#assert\b for system V"
+" compatibility.]:[assertion]"
+"[E:preprocess?Ignored for compatibility with ancient compilers.]"
+"[H:include-reference?Emit \b#include\b file paths on the standard error,"
+" one per line, indented to show nesting.]"
+"[T?If not \bgcc\b(1) then truncate identifiers to \alength\a"
+" characters for compatibility with old AT&T (I guess only Lucent needs"
+" them now) compilers.]#?[length]"
+"[V:version?Emit the \blibpp\b(3) version.]"
+"[X:argmode?Enable \aname\a=\avalue\a macro arguments for \beasel\b(1)"
+" compatibility.]"
+"[Y:standard?Add \adirectory\a to the list searched for"
+" \b#include\b \b<...>\b files.]:[directory]"
+
+"\n"
+"\n[ input [ output ] ]\n"
+"\n"
+
+"[+SEE ALSO?\bcc\b(1), \bgcc\b(1), \blibpp\b(3)]"
+;
+
+#include "pplib.h"
+
+#include <ctype.h>
+
+/*
+ * convert lint comments to pragmas
+ */
+
+static void
+pplint(char* head, char* comment, char* tail, int line)
+{
+ NoP(line);
+ if (strmatch(comment, "(ARGSUSED|PRINTFLIKE|PROTOLIB|SCANFLIKE|VARARGS)*([0-9])|CONSTCOND|CONSTANTCOND|CONSTANTCONDITION|EMPTY|FALLTHRU|FALLTHROUGH|LINTLIBRARY|LINTED*|NOTREACHED"))
+ {
+ strncopy(pp.token, comment, MAXTOKEN);
+ ppprintf("\n#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.token);
+ ppline(error_info.line, NiL);
+ }
+}
+
+/*
+ * if last!=0 then argv[opt_info.index]==0 with return(0)
+ * else if argv[opt_info.index]==0 then return(0)
+ * otherwise argv[opt_info.index] is the first unrecognized
+ * option with return(1)
+ *
+ * use last=0 if the preprocessor is combined with other passes
+ * so that unknown options may be interpreted for those passes
+ */
+
+int
+ppargs(char** argv, int last)
+{
+ register char* s;
+ register int c;
+ register int n;
+ char* p;
+
+ /*
+ * check the args and initialize
+ */
+
+ if (!error_info.id)
+ error_info.id = "cpp";
+ for (;;)
+ {
+ for (; c = optget(argv, usage); last = 0) switch (c)
+ {
+ case 'C':
+ ppop(PP_COMMENT, ppcomment);
+ break;
+ case 'D':
+ /*
+ * this allows single arg pp option extensions
+ * without touching cc
+ * (not all cc wrappers have -W...)
+ */
+
+ switch (*(s = opt_info.arg))
+ {
+ case '-':
+ case '+':
+ n = (*s++ == '-');
+ while (c = *s++) switch (c)
+ {
+ case 'C':
+ ppop(PP_COMPATIBILITY, n);
+ break;
+ case 'D':
+ if (n && ((c = strtol(s, &p, 0)) || p != s))
+ {
+ s = p;
+ n = c;
+ }
+ ppop(PP_DEBUG, -n);
+ break;
+ case 'F':
+ ppop(PP_FILENAME, n ? s : NiL);
+ goto hasarg;
+ case 'H':
+ ppop(PP_HOSTDIR, "-", n);
+ break;
+ case 'I':
+ ppop(PP_CDIR, "-", n);
+ break;
+ case 'K':
+ ppop(PP_KEYARGS, n);
+ break;
+ case 'L':
+ ppop(PP_LINEID, n && *s ? s : "line");
+ goto hasarg;
+ case 'M':
+ ppop(PP_MULTIPLE, !n);
+ break;
+ case 'P':
+ ppop(PP_PASSTHROUGH, n);
+ break;
+ case 'Q':
+ ppop(PP_DUMP, n);
+ break;
+ case 'R':
+ ppop(PP_TRANSITION, n);
+ break;
+ case 'S':
+ ppop(PP_STRICT, n);
+ break;
+ case 'T':
+ ppop(PP_TEST, s);
+ goto hasarg;
+ case 'V':
+ ppop(PP_VENDOR, "-", n);
+ break;
+ case 'W':
+ ppop(PP_WARN, n);
+ break;
+ case 'X':
+ ppop(PP_PROBE, n && *s ? s : 0);
+ goto hasarg;
+ case 'Z':
+ ppop(PP_POOL, n);
+ break;
+ case 'd':
+ pp.option |= DEFINITIONS;
+ break;
+ case 'm':
+ pp.state |= NOTEXT;
+ pp.option |= KEEPNOTEXT|DEFINITIONS|PREDEFINITIONS;
+ pp.linesync = 0;
+ break;
+ case '+':
+ ppop(PP_PLUSPLUS, n);
+ break;
+ default:
+ if (pp.optarg)
+ {
+ if ((c = (*pp.optarg)(n, c, s)) > 0) goto hasarg;
+ else if (!c) break;
+ }
+ error(1, "%c%s: unknown -D option overload", n ? '-' : '+', s - 1);
+ goto hasarg;
+ }
+ hasarg:
+ break;
+ case ':':
+ ppop(PP_OPTION, s + 1);
+ break;
+ case '%':
+ ppop(PP_DIRECTIVE, s + 1);
+ break;
+ case '_':
+ if (strmatch(s, "__GNUC__*"))
+ pp.arg_style |= STYLE_gnu;
+ else if (strmatch(s, "__(ANSI|STDC|STRICT)__*") || !(pp.arg_style & STYLE_gnu) && strmatch(s, "__STRICT_ANSI__*"))
+ ppop(PP_STRICT, 1);
+ else if (strmatch(s, "__cplusplus*"))
+ ppop(PP_PLUSPLUS, 1);
+ /*FALLTHROUGH*/
+ default:
+ ppop(PP_DEFINE, s);
+ break;
+ }
+ break;
+ case 'E':
+ /* historically ignored */
+ break;
+ case 'I':
+ if (!(s = opt_info.arg))
+ {
+ /*
+ * some compilers interpret `-I ...' as
+ * `-I-S' and arg ... while others interpret
+ * it as `-I...'
+ */
+
+ p = "-S";
+ if ((s = argv[opt_info.index]) && ((n = *s++) == '-' || n == '+') && *s++ == 'D')
+ {
+ if (isalpha(*s) || *s == '_')
+ while (isalnum(*++s) || *s == '_');
+ if (*s && *s != '=' && *s != '-' && *s != '+')
+ p = argv[opt_info.index++];
+ }
+ s = p;
+ }
+ switch (*s)
+ {
+ case '-':
+ case '+':
+ n = *(p = s++) == '-';
+ c = *s++;
+ if (!n && !*s) s = 0;
+ switch (c)
+ {
+ case 0:
+ ppop(PP_LOCAL);
+ break;
+ case 'C':
+ ppop(PP_CDIR, s, n);
+ break;
+ case 'D':
+ ppop(PP_DEFAULT, s);
+ break;
+ case 'H':
+ ppop(PP_HOSTDIR, s, n);
+ break;
+ case 'I':
+ ppop(PP_IGNORE, s);
+ break;
+ case 'M':
+ ppop(PP_IGNORELIST, s);
+ break;
+ case 'R':
+ ppop(PP_READ, s);
+ break;
+ case 'S':
+ ppop(PP_STANDARD, s);
+ break;
+ case 'T':
+ ppop(PP_TEXT, s);
+ break;
+ case 'V':
+ ppop(PP_VENDOR, s, n);
+ break;
+ default:
+ error(1, "%s: unknown -I option overload", p);
+ break;
+ }
+ break;
+ default:
+ ppop(PP_INCLUDE, s);
+ break;
+ }
+ break;
+ case 'M':
+ for (n = PP_deps; argv[opt_info.index]; opt_info.offset++)
+ {
+ switch (argv[opt_info.index][opt_info.offset])
+ {
+ case 'D':
+ n |= PP_deps_file;
+ continue;
+ case 'G':
+ n |= PP_deps_generated;
+ continue;
+ case 'M':
+ n |= PP_deps_local;
+ continue;
+ }
+ break;
+ }
+ ppop(PP_FILEDEPS, n);
+ break;
+ case 'P':
+ ppop(PP_LINE, (PPLINESYNC)0);
+ break;
+ case 'U':
+ ppop(PP_UNDEF, opt_info.arg);
+ break;
+
+ /*
+ * System V CCS compatibility
+ */
+
+ case 'A':
+ if (isalpha(opt_info.arg[0]) || opt_info.arg[0] == '_' || opt_info.arg[0] == '$')
+ ppop(PP_ASSERT, opt_info.arg);
+ break;
+ case 'H':
+ ppop(PP_INCREF, ppincref);
+ break;
+ case 'T':
+ if (!(pp.arg_style & STYLE_gnu))
+ ppop(PP_TRUNCATE, TRUNCLENGTH);
+ /* else enable ANSI trigraphs -- default */
+ break;
+ case 'V':
+ error(0, "%s", pp.version);
+ break;
+ case 'X':
+ pp.arg_mode = (*(opt_info.arg + 1) || pp.arg_mode && pp.arg_mode != *opt_info.arg) ? '-' : *opt_info.arg;
+ break;
+ case 'Y':
+ if (*(s = opt_info.arg) && *(s + 1) == ',')
+ {
+ if (*s != 'I') break;
+ s += 2;
+ }
+ ppop(PP_STANDARD, s);
+ break;
+
+ /*
+ * errors
+ */
+
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ if (!last)
+ {
+ opt_info.again = 1;
+ return(1);
+ }
+
+ /*
+ * cross your fingers
+ */
+
+ if (!(s = argv[opt_info.index]))
+ error(3, "%s", opt_info.arg);
+ if (opt_info.offset == 2 && (pp.arg_style & STYLE_gnu))
+ {
+ p = argv[opt_info.index + 1];
+ if (streq(s, "-$"))
+ {
+ ppop(PP_OPTION, "noid \"$\"");
+ goto ignore;
+ }
+ else if (streq(s, "-dD"))
+ {
+ pp.option |= DEFINITIONS;
+ goto ignore;
+ }
+ else if (streq(s, "-dM"))
+ {
+ pp.state |= NOTEXT;
+ pp.option |= KEEPNOTEXT|DEFINITIONS|PREDEFINITIONS;
+ pp.linesync = 0;
+ goto ignore;
+ }
+ else if (streq(s, "-imacros"))
+ {
+ if (p)
+ {
+ ppop(PP_READ, p);
+ opt_info.index++;
+ opt_info.offset = 0;
+ }
+ goto ignore;
+ }
+ else if (streq(s, "-include"))
+ {
+ if (p)
+ {
+ ppop(PP_TEXT, p);
+ opt_info.index++;
+ opt_info.offset = 0;
+ }
+ opt_info.offset = 0;
+ goto ignore;
+ }
+ else if (strneq(s, "-lang-", 6))
+ {
+ s += 6;
+ if (streq(s, "c"))
+ c = 0;
+ else if (streq(s, "c++"))
+ c = 1;
+ else if (streq(s, "objc"))
+ c = 2;
+ else if (streq(s, "objc++"))
+ c = 3;
+ ppop(PP_PLUSPLUS, c & 1);
+ if (c & 2)
+ ppop(PP_DIRECTIVE, "pragma pp:map \"/#(pragma )?import>/\" \"/#(pragma )?import(.*)/__STDPP__IMPORT__(\\2)/\"\n\
+#macdef __STDPP__IMPORT__(x)\n\
+#pragma pp:noallmultiple\n\
+#include x\n\
+#pragma pp:allmultiple\n\
+#endmac");
+ goto ignore;
+ }
+ else if (streq(s, "-lint"))
+ {
+ ppop(PP_COMMENT, pplint);
+ goto ignore;
+ }
+ }
+ s += opt_info.offset - 1;
+ if (strmatch(s, "i*.h"))
+ ppop((pp.arg_style & STYLE_gnu) || s[1] == '/' ? PP_READ : PP_TEXT, s + 1);
+ else if (strmatch(s, "*@(nostandard|nostdinc)*"))
+ ppop(PP_STANDARD, "");
+ else if (strmatch(s, "*@(exten|xansi)*|std"))
+ {
+ ppop(PP_COMPATIBILITY, 0);
+ ppop(PP_TRANSITION, 1);
+ }
+ else if (strmatch(s, "*@(ansi|conform|pedantic|stand|std1|strict[!-])*"))
+ {
+ ppop(PP_COMPATIBILITY, 0);
+ ppop(PP_STRICT, 1);
+ if (strmatch(s, "*pedantic*"))
+ ppop(PP_PEDANTIC, 1);
+ }
+ else if (strmatch(s, "*@(trans)*"))
+ {
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_TRANSITION, 1);
+ }
+ else if (strmatch(s, "*@(classic|compat|std0|tradition|[kK][n&+][rR])*"))
+ {
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_TRANSITION, 0);
+ }
+ else if (strmatch(s, "*@(plusplus|++)*"))
+ ppop(PP_PLUSPLUS, 1);
+ else if (strmatch(s, "*@(warn)*"))
+ ppop(PP_WARN, 1);
+
+ /*
+ * ignore unknown options
+ * the probe info takes care of these
+ * fails if an option value is in the next arg
+ * and this is the last option
+ */
+
+ if (argv[opt_info.index + 1] && argv[opt_info.index + 1][0] != '-' && argv[opt_info.index + 2] && argv[opt_info.index + 2][0] == '-')
+ {
+ opt_info.index++;
+ opt_info.offset = 0;
+ }
+ ignore:
+ while (argv[opt_info.index][opt_info.offset]) opt_info.offset++;
+ break;
+ }
+ if (!(s = argv[opt_info.index])) return(0);
+ switch (pp.arg_file)
+ {
+ case 0:
+ if (*s != '-' || *(s + 1)) ppop(PP_INPUT, s);
+ break;
+ case 1:
+ if (*s != '-' || *(s + 1)) ppop(PP_OUTPUT, s);
+ break;
+ default:
+ if (!last) return(1);
+ error(1, "%s: extraneous argument ignored", s);
+ break;
+ }
+ pp.arg_file++;
+ if (!argv[++opt_info.index]) return(0);
+
+ /*
+ * old versions allow options after file args
+ */
+ }
+}
diff --git a/usr/src/lib/libpp/common/ppbuiltin.c b/usr/src/lib/libpp/common/ppbuiltin.c
new file mode 100644
index 0000000000..b9a906f657
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppbuiltin.c
@@ -0,0 +1,397 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor builtin macro support
+ */
+
+#include "pplib.h"
+
+#include <times.h>
+
+/*
+ * process a #(...) builtin macro call
+ * `#(' has already been seen
+ */
+
+void
+ppbuiltin(void)
+{
+ register int c;
+ register char* p;
+ register char* a;
+
+ int n;
+ int op;
+ char* token;
+ char* t;
+ long number;
+ struct ppinstk* in;
+ struct pplist* list;
+ struct ppsymbol* sym;
+ Sfio_t* sp;
+
+ number = pp.state;
+ pp.state |= DISABLE|FILEPOP|NOSPACE;
+ token = pp.token;
+ p = pp.token = pp.tmpbuf;
+ *(a = pp.args) = 0;
+ if ((c = pplex()) != T_ID)
+ {
+ error(2, "%s: #(<identifier>...) expected", p);
+ *p = 0;
+ }
+ switch (op = (int)hashget(pp.strtab, p))
+ {
+ case V_DEFAULT:
+ n = 0;
+ p = pp.token = pp.valbuf;
+ if ((c = pplex()) == ',')
+ {
+ op = -1;
+ c = pplex();
+ }
+ pp.state &= ~NOSPACE;
+ for (;;)
+ {
+ if (!c)
+ {
+ error(2, "%s in #(...) argument", pptokchr(c));
+ break;
+ }
+ if (c == '(') n++;
+ else if (c == ')' && !n--) break;
+ else if (c == ',' && !n && op > 0) op = 0;
+ if (op) pp.token = pp.toknxt;
+ c = pplex();
+ }
+ *pp.token = 0;
+ pp.token = token;
+ pp.state = number;
+ break;
+ case V_EMPTY:
+ p = pp.valbuf;
+ if ((c = pplex()) == ')') *p = '1';
+ else
+ {
+ *p = '0';
+ n = 0;
+ for (;;)
+ {
+ if (!c)
+ {
+ error(2, "%s in #(...) argument", pptokchr(c));
+ break;
+ }
+ if (c == '(') n++;
+ else if (c == ')' && !n--) break;
+ c = pplex();
+ }
+ }
+ *(p + 1) = 0;
+ pp.token = token;
+ pp.state = number;
+ break;
+ case V_ITERATE:
+ n = 0;
+ pp.token = pp.valbuf;
+ if ((c = pplex()) != T_ID || !(sym = ppsymref(pp.symtab, pp.token)) || !sym->macro || sym->macro->arity != 1 || (c = pplex()) != ',')
+ {
+ error(2, "#(%s <macro(x)>, ...) expected", p);
+ for (;;)
+ {
+ if (!c)
+ {
+ error(2, "%s in #(...) argument", pptokchr(c));
+ break;
+ }
+ if (c == '(') n++;
+ else if (c == ')' && !n--) break;
+ c = pplex();
+ }
+ *pp.valbuf = 0;
+ }
+ else while (c != ')')
+ {
+ p = pp.token;
+ if (pp.token > pp.valbuf) *pp.token++ = ' ';
+ STRCOPY(pp.token, sym->name, a);
+ *pp.token++ = '(';
+ if (!c || !(c = pplex()))
+ {
+ pp.token = p;
+ error(2, "%s in #(...) argument", pptokchr(c));
+ break;
+ }
+ pp.state &= ~NOSPACE;
+ while (c)
+ {
+ if (c == '(') n++;
+ else if (c == ')' && !n--) break;
+ else if (c == ',' && !n) break;
+ pp.token = pp.toknxt;
+ c = pplex();
+ }
+ *pp.token++ = ')';
+ pp.state |= NOSPACE;
+ }
+ p = pp.valbuf;
+ pp.token = token;
+ pp.state = number;
+ break;
+ default:
+ pp.token = token;
+ while (c != ')')
+ {
+ if (!c)
+ {
+ error(2, "%s in #(...) argument", pptokchr(c));
+ break;
+ }
+ if ((c = pplex()) == T_ID && !*a)
+ strcpy(a, pp.token);
+ }
+ pp.state = number;
+ switch (op)
+ {
+ case V_ARGC:
+ c = -1;
+ for (in = pp.in; in; in = in->prev)
+ if ((in->type == IN_MACRO || in->type == IN_MULTILINE) && (in->symbol->flags & SYM_FUNCTION))
+ {
+ c = *((unsigned char*)(pp.macp->arg[0] - 2));
+ break;
+ }
+ sfsprintf(p = pp.valbuf, MAXTOKEN, "%d", c);
+ break;
+ case V_BASE:
+ p = (a = strrchr(error_info.file, '/')) ? a + 1 : error_info.file;
+ break;
+ case V_DATE:
+ if (!(p = pp.date))
+ {
+ time_t tm;
+
+ time(&tm);
+ a = p = ctime(&tm) + 4;
+ *(p + 20) = 0;
+ for (p += 7; *p = *(p + 9); p++);
+ pp.date = p = strdup(a);
+ }
+ break;
+ case V_FILE:
+ p = error_info.file;
+ break;
+ case V_LINE:
+ sfsprintf(p = pp.valbuf, MAXTOKEN, "%d", error_info.line);
+ break;
+ case V_PATH:
+ p = pp.path;
+ break;
+ case V_SOURCE:
+ p = error_info.file;
+ for (in = pp.in; in->prev; in = in->prev)
+ if (in->prev->type == IN_FILE && in->file)
+ p = in->file;
+ break;
+ case V_STDC:
+ p = pp.valbuf;
+ p[0] = ((pp.state & (COMPATIBILITY|TRANSITION)) || (pp.mode & (HOSTED|HOSTEDTRANSITION)) == (HOSTED|HOSTEDTRANSITION)) ? '0' : '1';
+ p[1] = 0;
+ break;
+ case V_TIME:
+ if (!(p = pp.time))
+ {
+ time_t tm;
+
+ time(&tm);
+ p = ctime(&tm) + 11;
+ *(p + 8) = 0;
+ pp.time = p = strdup(p);
+ }
+ break;
+ case V_VERSION:
+ p = (char*)pp.version;
+ break;
+ case V_DIRECTIVE:
+ pp.state |= NEWLINE;
+ pp.mode |= RELAX;
+ strcpy(p = pp.valbuf, "#");
+ break;
+ case V_GETENV:
+ if (!(p = getenv(a))) p = "";
+ break;
+ case V_GETMAC:
+ p = (sym = pprefmac(a, REF_NORMAL)) ? sym->macro->value : "";
+ break;
+ case V_GETOPT:
+ sfsprintf(p = pp.valbuf, MAXTOKEN, "%ld", ppoption(a));
+ break;
+ case V_GETPRD:
+ p = (list = (struct pplist*)hashget(pp.prdtab, a)) ? list->value : "";
+ break;
+ case V__PRAGMA:
+ if ((c = pplex()) == '(')
+ {
+ number = pp.state;
+ pp.state |= NOSPACE|STRIP;
+ c = pplex();
+ pp.state = number;
+ if (c == T_STRING || c == T_WSTRING)
+ {
+ if (!(sp = sfstropen()))
+ error(3, "temporary buffer allocation error");
+ sfprintf(sp, "#%s %s\n", dirname(PRAGMA), pp.token);
+ a = sfstruse(sp);
+ if ((c = pplex()) == ')')
+ {
+ pp.state |= NEWLINE;
+ PUSH_BUFFER(p, a, 1);
+ }
+ sfstrclose(sp);
+ }
+ }
+ if (c != ')')
+ error(2, "%s: (\"...\") expected", p);
+ return;
+ case V_FUNCTION:
+
+#define BACK(a,p) ((a>p)?*--a:(number++?0:((p=pp.outbuf+PPBUFSIZ),(a=pp.outbuf+2*PPBUFSIZ),*--a)))
+#define PEEK(a,p) ((a>p)?*(a-1):(number?0:*(pp.outbuf+2*PPBUFSIZ-1)))
+
+ number = pp.outbuf == pp.outb;
+ a = pp.outp;
+ p = pp.outb;
+ op = 0;
+ while (c = BACK(a, p))
+ {
+ if (c == '"' || c == '\'')
+ {
+ op = 0;
+ while ((n = BACK(a, p)) && n != c || PEEK(a, p) == '\\');
+ }
+ else if (c == '\n')
+ {
+ token = a;
+ while (c = BACK(a, p))
+ if (c == '\n')
+ {
+ a = token;
+ break;
+ }
+ else if (c == '#' && PEEK(a, p) == '\n')
+ break;
+ }
+ else if (c == ' ')
+ /*ignore*/;
+ else if (c == '{') /* '}' */
+ op = 1;
+ else if (op == 1)
+ {
+ if (c == ')')
+ {
+ op = 2;
+ n = 1;
+ }
+ else
+ op = 0;
+ }
+ else if (op == 2)
+ {
+ if (c == ')')
+ n++;
+ else if (c == '(' && !--n)
+ op = 3;
+ }
+ else if (op == 3)
+ {
+ if (ppisidig(c))
+ {
+ for (t = p, token = a; ppisidig(PEEK(a, p)); a--);
+ for (p = pp.valbuf + 1; a <= token; *p++ = *a++);
+ *p = 0;
+ p = pp.valbuf + 1;
+ if (streq(p, "for") || streq(p, "if") || streq(p, "switch") || streq(p, "while"))
+ {
+ op = 0;
+ p = t;
+ continue;
+ }
+ }
+ else
+ op = 0;
+ break;
+ }
+ }
+ if (op == 3)
+ strncpy(pp.funbuf, p, sizeof(pp.funbuf) - 1);
+ else if (*pp.funbuf)
+ p = pp.funbuf;
+ else
+ p = "__FUNCTION__";
+ break;
+ default:
+ if (pp.builtin && (a = (*pp.builtin)(pp.valbuf, p, a)))
+ p = a;
+ break;
+ }
+ break;
+ }
+ if (strchr(p, MARK))
+ {
+ a = pp.tmpbuf;
+ strcpy(a, p);
+ c = p != pp.valbuf;
+ p = pp.valbuf + c;
+ for (;;)
+ {
+ if (p < pp.valbuf + MAXTOKEN - 2)
+ switch (*p++ = *a++)
+ {
+ case 0:
+ break;
+ case MARK:
+ *p++ = MARK;
+ /*FALLTHROUGH*/
+ default:
+ continue;
+ }
+ break;
+ }
+ p = pp.valbuf + c;
+ }
+ if (p == pp.valbuf)
+ PUSH_STRING(p);
+ else
+ {
+ if (p == pp.valbuf + 1)
+ *pp.valbuf = '"';
+ else
+ {
+ if (strlen(p) > MAXTOKEN - 2)
+ error(1, "%-.16s: builtin value truncated", p);
+ sfsprintf(pp.valbuf, MAXTOKEN, "\"%-.*s", MAXTOKEN - 2, p);
+ }
+ PUSH_QUOTE(pp.valbuf, 1);
+ }
+}
diff --git a/usr/src/lib/libpp/common/ppcall.c b/usr/src/lib/libpp/common/ppcall.c
new file mode 100644
index 0000000000..8e273dc92f
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppcall.c
@@ -0,0 +1,452 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor macro call
+ */
+
+#include "pplib.h"
+
+#include <ctype.h>
+
+/*
+ * call a macro by pushing its value on the input stream
+ * only the macro token itself has been consumed
+ * -1 returned if macro disabled
+ * 0 returned if tok==0 and sym->mac->value to be copied to output by caller
+ * 1 returned if value pushed on input
+ */
+
+int
+ppcall(register struct ppsymbol* sym, int tok)
+{
+ register int c;
+ register char* p;
+ register char* q;
+ register struct ppmacro* mac;
+ int n;
+ int m;
+ int ret;
+ int old_hidden;
+ int last_line;
+ long old_state;
+ char* last_file;
+ char* old_token;
+ struct ppmacstk* mp;
+ struct ppinstk* old_in;
+ struct ppinstk* kp;
+ struct pptuple* tp;
+
+ ret = -1;
+ sym->flags |= SYM_NOTICED;
+ if (mac = sym->macro)
+ {
+ count(macro);
+ if ((sym->flags & SYM_PREDICATE) && (pp.state & (CONDITIONAL|WARN)) == (CONDITIONAL|WARN))
+ error(1, "%s: macro definition overrides assertion: use #%s ...", sym->name, sym->name);
+ if (sym->flags & SYM_DISABLED)
+#if COMPATIBLE
+ if ((pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY || !mac->arity)
+#endif
+ {
+ pp.mode |= MARKMACRO;
+#if COMPATIBLE
+ if ((pp.state & (COMPATIBILITY|STRICT)) == (COMPATIBILITY|STRICT))
+ error(1, "%s: macro recursion inhibited", sym->name);
+#endif
+ goto disable;
+ }
+ if ((sym->flags & SYM_PREDEFINED) && !(pp.mode & (HOSTED|INACTIVE)))
+ {
+#if COMPATIBLE
+ if (*sym->name != '_' && !(pp.state & COMPATIBILITY))
+#else
+ if (*sym->name != '_')
+#endif
+ {
+ if (pp.state & STRICT)
+ {
+ error(1, "%s: obsolete predefined symbol expansion disabled", sym->name);
+ goto disable;
+ }
+ error(1, "%s: obsolete predefined symbol expanded%s", sym->name, (pp.state & DIRECTIVE) ? "" : " outside of directive");
+ }
+ else if (!(pp.state & DIRECTIVE) && mac->value && (ppisdig(*mac->value) || *mac->value == '#'))
+ error(1, "%s: predefined symbol expanded outside of directive", sym->name);
+ }
+ debug((-5, "macro %s = %s", sym->name, mac->value));
+ if (pp.macref)
+ (*pp.macref)(sym, error_info.file, error_info.line, (pp.state & CONDITIONAL) ? REF_IF : REF_NORMAL, 0L);
+ if (tp = mac->tuple)
+ {
+ old_state = pp.state;
+ pp.state |= DEFINITION|NOSPACE;
+ old_token = pp.token;
+ n = 2 * MAXTOKEN;
+ pp.token = p = oldof(0, char, 0, n);
+ q = p + MAXTOKEN;
+ *pp.token++ = ' ';
+ old_hidden = pp.hidden;
+ while (c = pplex())
+ {
+ if (c == '\n')
+ {
+ pp.hidden++;
+ pp.state |= HIDDEN|NEWLINE;
+ old_state |= HIDDEN|NEWLINE;
+ error_info.line++;
+ }
+ else if (c == '#')
+ {
+ ungetchr(c);
+ break;
+ }
+ else
+ {
+ for (;;)
+ {
+ if (streq(pp.token, tp->token))
+ {
+ if (!(tp = tp->match))
+ break;
+ if (!tp->nomatch)
+ {
+ free(p);
+ pp.state = old_state;
+ pp.token = old_token;
+ PUSH_TUPLE(sym, tp->token);
+ ret = 1;
+ goto disable;
+ }
+ }
+ else if (!(tp = tp->nomatch))
+ break;
+ }
+ if (!tp)
+ {
+ pp.token = pp.toknxt;
+ break;
+ }
+ }
+ if ((pp.token = pp.toknxt) > q)
+ {
+ c = pp.token - p;
+ p = newof(p, char, n += MAXTOKEN, 0);
+ q = p + n - MAXTOKEN;
+ pp.token = p + c;
+ }
+ *pp.token++ = ' ';
+ }
+ if (pp.token > p && *(pp.token - 1) == ' ')
+ pp.token--;
+ if (pp.hidden != old_hidden)
+ *pp.token++ = '\n';
+ else
+ *pp.token++ = ' ';
+ *pp.token = 0;
+ pp.state = old_state;
+ pp.token = old_token;
+ if (*p)
+ PUSH_RESCAN(p);
+ else
+ free(p);
+ if (!mac->value)
+ goto disable;
+ }
+ if (sym->flags & SYM_FUNCTION)
+ {
+ /*
+ * a quick and dirty '(' peek to avoid possibly
+ * inappropriate ungetchr()'s below
+ */
+
+ for (p = pp.in->nextchr; isspace(*p); p++);
+ if ((c = *p) != '(' && c != '/' && c != 0 && c != MARK)
+ goto disable;
+ old_token = pp.token;
+ mp = pp.macp->next;
+ if ((pp.token = (char*)&mp->arg[mac->arity + 1]) > pp.maxmac)
+ error(3, "%s: too many nested function-like macros", sym->name);
+ old_hidden = pp.hidden;
+ old_state = pp.state;
+ pp.state |= DEFINITION|FILEPOP|NOSPACE;
+ while ((c = pplex()) == '\n')
+ {
+ pp.hidden++;
+ pp.state |= HIDDEN|NEWLINE;
+ old_state |= HIDDEN|NEWLINE;
+ error_info.line++;
+ }
+ if (c != '(')
+ {
+ pp.state = old_state;
+ if (c)
+ {
+ p = pp.toknxt;
+ while (p > pp.token)
+ ungetchr(*--p);
+#if COMPATIBLE
+ if ((pp.state & (COMPATIBILITY|STRICT)) == (COMPATIBILITY|STRICT))
+ error(1, "%s: macro arguments omitted", sym->name);
+#endif
+ if (c == T_ID && !(pp.state & HIDDEN))
+ ungetchr(' ');
+ }
+ if (pp.hidden != old_hidden)
+ {
+ ungetchr('\n');
+ error_info.line--;
+ if (pp.hidden && !--pp.hidden)
+ pp.state &= ~HIDDEN;
+ }
+ pp.token = old_token;
+ goto disable;
+ }
+ pp.state = old_state;
+
+ /*
+ * arg[i][-1] is an extra char for each actual i
+ * for a possible ungetchr('"') during IN_QUOTE
+ * arg[i][-1]==0 if arg i need not be expanded
+ * arg[0][-2] holds the actual arg count
+ */
+
+ c = 0;
+ m = 0;
+ n = 0;
+ mp = pp.macp->next;
+ p = pp.token = (char*)&mp->arg[mac->arity + 1];
+ pp.state |= COLLECTING|NOEXPAND;
+ pp.state &= ~FILEPOP;
+ sym->flags |= SYM_ACTIVE;
+ old_in = pp.in;
+ last_line = error_info.line;
+ last_file = error_info.file;
+ mp->line = error_info.line;
+#if MACKEYARGS
+ if (pp.option & KEYARGS)
+ {
+ for (c = 0; c < mac->arity; c++)
+ mp->arg[c] = mac->args.key[c].value + 1;
+ mp->arg[0]++;
+ }
+ else
+#endif
+ {
+ *++p = ' ';
+ mp->arg[0] = ++p;
+ }
+#if MACKEYARGS
+ keyarg:
+ if (pp.option & KEYARGS)
+ {
+ pp.state |= NOSPACE;
+ switch (pplex())
+ {
+ case T_ID:
+ break;
+ case ')': /* no actual key args */
+ if (!(pp.state & NOEXPAND))
+ pp.state |= NOEXPAND;
+ for (c = 0; c < mac->arity; c++)
+ mp->arg[c][-1] = 0;
+ c = 0;
+ goto endactuals;
+ default:
+ error(3, "%s: invalid keyword macro argument", pp.token);
+ break;
+ }
+ for (c = 0; c < mac->arity; c++)
+ if (streq(pp.token, mac->args.key[c].name)) break;
+ if (c >= mac->arity)
+ error(2, "%s: invalid macro argument keyword", pp.token);
+ if (pplex() != '=')
+ error(2, "= expected in keyword macro argument");
+ pp.state &= ~NOSPACE;
+ if (!c)
+ p++;
+ pp.token = mp->arg[c] = ++p;
+ }
+#endif
+ for (;;)
+ {
+ if ((pp.mactop = pp.token = p) >= pp.maxmac)
+ error(3, "%s: too many nested function-like macros", sym->name);
+ switch (pplex())
+ {
+ case '(':
+ n++;
+ break;
+ case ')':
+ if (!n--)
+ {
+ if (p > mp->arg[c] && *(p - 1) == ' ')
+ p--;
+ if (p > mp->arg[c] && *(p - 1) == '\\')
+ {
+ for (q = mp->arg[c]; q < p; q++)
+ if (*q == '\\')
+ q++;
+ if (q > p)
+ *p++ = '\\';
+ }
+#if MACKEYARGS
+ *p = 0;
+ m++;
+#endif
+ goto endactuals;
+ }
+ break;
+ case ',':
+ if (!n && (m++, (c < mac->arity - 1 || !(sym->flags & SYM_VARIADIC))))
+ {
+ if (p > mp->arg[c] && *(p - 1) == ' ')
+ p--;
+ *p++ = 0;
+ if (!(pp.state & NOEXPAND))
+ pp.state |= NOEXPAND;
+ else
+ mp->arg[c][-1] = 0;
+#if MACKEYARGS
+ if (pp.option & KEYARGS)
+ {
+ pp.token = p + 1;
+ goto keyarg;
+ }
+#endif
+ {
+ if ((pp.state & STRICT) && p == mp->arg[c])
+ error(1, "%s: macro call argument %d is null", sym->name, c + 1);
+ if (c < mac->arity)
+ c++;
+ *p++ = ' ';
+ }
+ pp.toknxt = mp->arg[c] = p;
+ }
+ break;
+ case 0:
+ if (pp.in == old_in)
+ kp = 0;
+ else
+ for (kp = pp.in; kp && kp != old_in; kp = kp->prev);
+ if (!kp)
+ {
+ error(
+#if COMPATIBLE
+ (pp.state & COMPATIBILITY) ? 3 :
+#endif
+ 2, "%s: %s in macro argument list", sym->name, pptokchr(0));
+ goto endactuals;
+ }
+ continue;
+ case '\n':
+ pp.state |= HIDDEN;
+ error_info.line++;
+ pp.hidden++;
+ /*FALLTHROUGH*/
+ case ' ':
+ if (p > mp->arg[c] && *(p - 1) != ' ') *p++ = ' ';
+ continue;
+ }
+ p = pp.toknxt;
+ if (error_info.line != last_line)
+ {
+ SETLINE(p, error_info.line);
+ last_line = error_info.line;
+ }
+ if (error_info.file != last_file)
+ {
+ SETFILE(p, error_info.file);
+ last_file = error_info.file;
+ }
+ }
+ endactuals:
+ if (pp.state & NOEXPAND)
+ mp->arg[c][-1] = 0;
+ pp.token = old_token;
+ if (pp.in != old_in)
+ {
+ for (kp = pp.in; kp && kp != old_in; kp = kp->prev);
+ if (kp)
+ error(2, "%s: macro call starts and ends in different files", sym->name);
+ }
+ pp.state &= ~(COLLECTING|FILEPOP|NOEXPAND);
+ sym->flags &= ~SYM_ACTIVE;
+#if MACKEYARGS
+ if (!(pp.option & KEYARGS))
+#endif
+ {
+ if (p > mp->arg[0] && ++m || (sym->flags & SYM_VARIADIC))
+ c++;
+ if (c != mac->arity && !(sym->flags & SYM_EMPTY))
+ {
+ n = mac->arity;
+ if (!(sym->flags & SYM_VARIADIC))
+ error(1, "%s: %d actual argument%s expected", sym->name, n, n == 1 ? "" : "s");
+ else if (c < --n)
+ error(1, "%s: at least %d actual argument%s expected", sym->name, n, n == 1 ? "" : "s");
+#if COMPATIBLE
+ if (!c && (pp.state & (COMPATIBILITY|STRICT)) == (COMPATIBILITY|STRICT))
+ goto disable;
+#endif
+ }
+ if (!c)
+ ++c;
+ while (c < mac->arity)
+ mp->arg[c++] = (char*)"\0" + 1;
+ }
+ mp->arg[0][-2] = m;
+ *p++ = 0;
+ nextframe(mp, p);
+ count(function);
+ }
+ if (!tok && (sym->flags & SYM_NOEXPAND))
+ {
+ if (sym->flags & SYM_FUNCTION)
+ popframe(mp);
+ ret = !mac->size;
+ }
+ else if (!(pp.state & HEADER) || (pp.option & HEADEREXPANDALL) || pp.in->type != IN_COPY)
+ {
+ if (sym->flags & SYM_MULTILINE)
+ PUSH_MULTILINE(sym);
+ else
+ PUSH_MACRO(sym);
+ ret = 1;
+ }
+ }
+ disable:
+ if (ret < 0 && sym->hidden && !(pp.mode & EXPOSE) && !(pp.state & HEADER) && (pp.in->type == IN_FILE || pp.in->type == IN_MACRO || pp.in->type == IN_EXPAND))
+ {
+ struct ppinstk* inp;
+
+ for (inp = pp.in; inp->type != IN_FILE && inp->prev; inp = inp->prev);
+ sfsprintf(pp.hidebuf, MAXTOKEN, "_%d_%s_hIDe", inp->index, sym->name);
+ PUSH_STRING(pp.hidebuf);
+ ret = 1;
+ }
+ pp.state &= ~NEWLINE;
+ pp.in->flags |= IN_tokens;
+ count(token);
+ return ret;
+}
diff --git a/usr/src/lib/libpp/common/ppcomment.c b/usr/src/lib/libpp/common/ppcomment.c
new file mode 100644
index 0000000000..c938bc2e67
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppcomment.c
@@ -0,0 +1,35 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common preprocessor comment handler
+ */
+
+#include "pplib.h"
+
+void
+ppcomment(char* head, char* comment, char* tail, int line)
+{
+ NoP(line);
+ ppprintf("%s%-.*s%s", head, MAXTOKEN - 4, comment, tail);
+}
diff --git a/usr/src/lib/libpp/common/ppcontext.c b/usr/src/lib/libpp/common/ppcontext.c
new file mode 100644
index 0000000000..220481ab87
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppcontext.c
@@ -0,0 +1,65 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor context switch
+ *
+ * args op return
+ * (0,0) free current context 0
+ * (0,1) save current context current
+ * (p,0) free context p 0
+ * (p,1) make p current context previous
+ */
+
+#include "pplib.h"
+
+void*
+ppcontext(void* context, int flags)
+{
+ struct ppcontext* np = (struct ppcontext*)context;
+ struct ppcontext* op;
+
+ if (flags & 01)
+ {
+ if (!(op = pp.context)) op = pp.context = newof(0, struct ppcontext, 1, 0);
+ memcpy(op, _PP_CONTEXT_BASE_, sizeof(struct ppcontext));
+ }
+ else
+ {
+ if (!(op = np)) op = (struct ppcontext*)_PP_CONTEXT_BASE_;
+ if (op->filtab) hashfree(op->filtab);
+ if (op->prdtab) hashfree(op->prdtab);
+ if (op->symtab) hashfree(op->symtab);
+ if (op->date) free(op->date);
+ if (op->time) free(op->time);
+ if (np)
+ {
+ free(np);
+ np = 0;
+ }
+ memzero(op, sizeof(struct ppcontext));
+ op = 0;
+ }
+ if (np) memcpy(_PP_CONTEXT_BASE_, np, sizeof(struct ppcontext));
+ return((void*)op);
+}
diff --git a/usr/src/lib/libpp/common/ppcontrol.c b/usr/src/lib/libpp/common/ppcontrol.c
new file mode 100644
index 0000000000..a5d9974927
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppcontrol.c
@@ -0,0 +1,2295 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor control directive support
+ */
+
+#include "pplib.h"
+
+#include <regex.h>
+
+#define TOKOP_DUP (1<<0)
+#define TOKOP_STRING (1<<1)
+#define TOKOP_UNSET (1<<2)
+
+struct edit
+{
+ struct edit* next;
+ regex_t re;
+};
+
+struct map
+{
+ struct map* next;
+ regex_t re;
+ struct edit* edit;
+};
+
+#define RESTORE (COLLECTING|CONDITIONAL|DEFINITION|DIRECTIVE|DISABLE|EOF2NL|HEADER|NOSPACE|NOVERTICAL|PASSEOF|STRIP)
+
+/*
+ * common predicate assertion operations
+ * op is DEFINE or UNDEF
+ */
+
+static void
+assert(int op, char* pred, char* args)
+{
+ register struct pplist* a;
+ register struct ppsymbol* sym;
+ register struct pplist* p;
+ register struct pplist* q;
+
+ if (!args) switch (op)
+ {
+ case DEFINE:
+ goto mark;
+ case UNDEF:
+ a = 0;
+ goto unmark;
+ }
+ if (a = (struct pplist*)hashget(pp.prdtab, pred))
+ {
+ p = 0;
+ q = a;
+ while (q)
+ {
+ if (streq(q->value, args))
+ {
+ if (op == DEFINE) return;
+ q = q->next;
+ if (p) p->next = q;
+ else a = q;
+ }
+ else
+ {
+ p = q;
+ q = q->next;
+ }
+ }
+ if (op == UNDEF)
+ {
+ unmark:
+ hashput(pp.prdtab, pred, a);
+ if (sym = ppsymref(pp.symtab, pred))
+ sym->flags &= ~SYM_PREDICATE;
+ return;
+ }
+ }
+ if (op == DEFINE)
+ {
+ p = newof(0, struct pplist, 1, 0);
+ p->next = a;
+ p->value = strdup(args);
+ hashput(pp.prdtab, NiL, p);
+ mark:
+ if ((pp.state & COMPILE) && pp.truncate) return;
+ if (sym = ppsymset(pp.symtab, pred))
+ sym->flags |= SYM_PREDICATE;
+ }
+}
+
+/*
+ * tokenize string ppop()
+ *
+ * op PP_* op
+ * name option name
+ * s string of option values
+ * n option sense
+ * flags TOKOP_* flags
+ */
+
+static void
+tokop(int op, char* name, register char* s, register int n, int flags)
+{
+ register int c;
+ register char* t;
+
+ if (!(flags & TOKOP_UNSET) && !n) error(2, "%s: option cannot be unset", name);
+ else if (!s) ppop(op, s, n);
+ else if (flags & TOKOP_STRING)
+ {
+ PUSH_LINE(s);
+ for (;;)
+ {
+ pp.state &= ~NOSPACE;
+ c = pplex();
+ pp.state |= NOSPACE;
+ if (!c) break;
+ if (c != ' ')
+ ppop(op, (flags & TOKOP_DUP) ? strdup(pp.token) : pp.token, n);
+ }
+ POP_LINE();
+ }
+ else do
+ {
+ while (*s == ' ') s++;
+ for (t = s; *t && *t != ' '; t++);
+ if (*t) *t++ = 0;
+ else t = 0;
+ if (*s) ppop(op, (flags & TOKOP_DUP) ? strdup(s) : s, n);
+ } while (s = t);
+}
+
+/*
+ * return symbol pointer for next token macro (re)definition
+ */
+
+static struct ppsymbol*
+macsym(int tok)
+{
+ register struct ppsymbol* sym;
+
+ if (tok != T_ID)
+ {
+ error(2, "%s: invalid macro name", pptokstr(pp.token, 0));
+ return 0;
+ }
+ sym = pprefmac(pp.token, REF_CREATE);
+ if ((sym->flags & SYM_FINAL) && (pp.mode & HOSTED)) return 0;
+ if (sym->flags & (SYM_ACTIVE|SYM_READONLY))
+ {
+ if (!(pp.option & ALLPOSSIBLE))
+ error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active");
+ return 0;
+ }
+ if (!sym->macro) sym->macro = newof(0, struct ppmacro, 1, 0);
+ return sym;
+}
+
+/*
+ * get one space canonical pplex() line, sans '\n', and place in p
+ * x is max+1 pos in p
+ * 0 returned if line too large
+ * otherwise end of p ('\0') returned
+ */
+
+static char*
+getline(register char* p, char* x, int disable)
+{
+ register int c;
+ register char* s;
+ char* b;
+ long restore;
+
+ restore = pp.state & (NOSPACE|STRIP);
+ pp.state &= ~(NEWLINE|NOSPACE|STRIP);
+ pp.state |= EOF2NL;
+ b = p;
+ while ((c = pplex()) != '\n')
+ {
+ if (disable)
+ {
+ if (c == ' ')
+ /*ignore*/;
+ else if (disable == 1)
+ disable = (c == T_ID && streq(pp.token, pp.pass)) ? 2 : 0;
+ else
+ {
+ disable = 0;
+ if (c == ':')
+ pp.state |= DISABLE;
+ }
+ }
+ s = pp.token;
+ while (*p = *s++)
+ if (++p >= x)
+ {
+ p = 0;
+ goto done;
+ }
+ }
+ if (p > b && *(p - 1) == ' ')
+ p--;
+ if (p >= x)
+ p = 0;
+ else
+ *p = 0;
+ done:
+ pp.state &= ~(NOSPACE|STRIP);
+ pp.state |= restore;
+ return p;
+}
+
+/*
+ * regex error handler
+ */
+
+void
+regfatal(regex_t* p, int level, int code)
+{
+ char buf[128];
+
+ regerror(code, p, buf, sizeof(buf));
+ regfree(p);
+ error(level, "regular expression: %s", buf);
+}
+
+/*
+ * process a single directive line
+ */
+
+int
+ppcontrol(void)
+{
+ register char* p;
+ register int c;
+ register int n;
+ register char* s;
+ register struct ppmacro* mac;
+ register struct ppsymbol* sym;
+ struct edit* edit;
+ struct map* map;
+ struct ppfile* fp;
+ int o;
+ int directive;
+ long restore;
+ struct pptuple* rp;
+ struct pptuple* tp;
+ char* v;
+ int emitted;
+
+ union
+ {
+ struct map* best;
+ struct ppinstk* inp;
+ struct pplist* list;
+ char* string;
+ struct ppsymbol* symbol;
+ int type;
+ PPLINESYNC linesync;
+ } var;
+
+ static char __va_args__[] = "__VA_ARGS__";
+ static int i0;
+ static int i1;
+ static int i2;
+ static int i3;
+ static int i4;
+
+ static long n1;
+ static long n2;
+ static long n3;
+
+ static char* p0;
+ static char* p1;
+ static char* p2;
+ static char* p3;
+ static char* p4;
+ static char* p5;
+ static char* p6;
+
+ static struct ppmacro old;
+ static char* formargs[MAXFORMALS];
+#if MACKEYARGS
+ static char* formvals[MAXFORMALS];
+#endif
+
+ emitted = 0;
+ if (pp.state & SKIPCONTROL) pp.level--;
+ restore = (pp.state & RESTORE)|NEWLINE;
+ if (pp.state & PASSTHROUGH) restore |= DISABLE;
+ else restore &= ~DISABLE;
+ pp.state &= ~(NEWLINE|RESTORE|SKIPCONTROL);
+ pp.state |= DIRECTIVE|DISABLE|EOF2NL|NOSPACE|NOVERTICAL;
+#if COMPATIBLE
+ if ((pp.state & (COMPATIBILITY|STRICT)) == COMPATIBILITY || (pp.mode & HOSTED)) pp.state &= ~NOVERTICAL;
+#else
+ if (pp.mode & HOSTED) pp.state &= ~NOVERTICAL;
+#endif
+ switch (c = pplex())
+ {
+ case T_DECIMAL:
+ case T_OCTAL:
+ if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "# <line> [ \"<file>\" [ <type> ] ]: non-standard directive");
+ directive = INCLUDE;
+ goto linesync;
+ case T_ID:
+ switch (directive = (int)hashref(pp.dirtab, pp.token))
+ {
+ case ELIF:
+ else_if:
+ if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
+ goto eatdirective;
+ if (pp.control <= pp.in->control)
+ {
+ error(2, "no matching #%s for #%s", dirname(IF), dirname(ELIF));
+ goto eatdirective;
+ }
+ if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard;
+ if (*pp.control & HADELSE)
+ {
+ error(2, "invalid #%s after #%s", dirname(ELIF), dirname(ELSE));
+ *pp.control |= SKIP;
+ goto eatdirective;
+ }
+ if (*pp.control & KEPT)
+ {
+ *pp.control |= SKIP;
+ goto eatdirective;
+ }
+ if (directive == IFDEF || directive == IFNDEF)
+ {
+ *pp.control &= ~SKIP;
+ goto else_ifdef;
+ }
+ conditional:
+ if (ppexpr(&i1))
+ {
+ *pp.control &= ~SKIP;
+ *pp.control |= KEPT;
+ }
+ else *pp.control |= SKIP;
+ c = (pp.state & NEWLINE) ? '\n' : ' ';
+ goto eatdirective;
+ case ELSE:
+ if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
+ goto eatdirective;
+ if ((pp.option & ELSEIF) && (c = pplex()) == T_ID && ((n = (int)hashref(pp.dirtab, pp.token)) == IF || n == IFDEF || n == IFNDEF))
+ {
+ error(1, "#%s %s is non-standard -- use #%s", dirname(directive), dirname(n), dirname(ELIF));
+ directive = n;
+ goto else_if;
+ }
+ if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ELSE));
+ else
+ {
+ if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard;
+ if (!(*pp.control & KEPT))
+ {
+ *pp.control &= ~SKIP;
+ *pp.control |= HADELSE|KEPT;
+ }
+ else
+ {
+ if (*pp.control & HADELSE) error(2, "more than one #%s for #%s", dirname(ELSE), dirname(IF));
+ *pp.control |= HADELSE|SKIP;
+ }
+ }
+ goto enddirective;
+ case ENDIF:
+ if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
+ goto eatdirective;
+ if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ENDIF));
+ else if (--pp.control == pp.in->control && pp.in->symbol)
+ {
+ if (pp.in->flags & IN_endguard) pp.in->flags |= IN_noguard;
+ else
+ {
+ pp.in->flags &= ~IN_tokens;
+ pp.in->flags |= IN_endguard;
+ }
+ }
+ goto enddirective;
+ case IF:
+ case IFDEF:
+ case IFNDEF:
+ if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev)
+ goto eatdirective;
+ pushcontrol();
+ SETIFBLOCK(pp.control);
+ if (*pp.control & SKIP)
+ {
+ *pp.control |= KEPT;
+ goto eatdirective;
+ }
+ if (directive == IF) goto conditional;
+ else_ifdef:
+ if ((c = pplex()) == T_ID)
+ {
+ sym = pprefmac(pp.token, REF_IF);
+ if (directive == IFNDEF && pp.control == pp.in->control + 1)
+ {
+ if (pp.in->flags & (IN_defguard|IN_endguard))
+ pp.in->flags |= IN_noguard;
+ else
+ {
+ pp.in->flags |= IN_defguard;
+ if (!(pp.in->flags & IN_tokens))
+ pp.in->symbol = sym ? sym : pprefmac(pp.token, REF_CREATE);
+ }
+ }
+ }
+ else
+ {
+ sym = 0;
+ if (!(pp.mode & HOSTED))
+ error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
+ }
+ *pp.control |= ((sym != 0) == (directive == IFDEF)) ? KEPT : SKIP;
+ goto enddirective;
+ case INCLUDE:
+ if (*pp.control & SKIP)
+ {
+ pp.state |= HEADER;
+ c = pplex();
+ pp.state &= ~HEADER;
+ goto eatdirective;
+ }
+ pp.state &= ~DISABLE;
+ pp.state |= HEADER|STRIP;
+ switch (c = pplex())
+ {
+ case T_STRING:
+ p = pp.token;
+ do pp.token = pp.toknxt; while ((c = pplex()) == T_STRING);
+ *pp.token = 0;
+ pp.token = p;
+ /*FALLTHROUGH*/
+ case T_HEADER:
+ header:
+ if (!*pp.token)
+ {
+ error(2, "#%s: null file name", dirname(INCLUDE));
+ break;
+ }
+ if (*pp.token == '/' && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: reference to %s is not portable", dirname(INCLUDE), pp.token);
+ n = ppsearch(pp.token, c, SEARCH_INCLUDE);
+ break;
+ case '<':
+ /*
+ * HEADEREXPAND|HEADEREXPANDALL gets us here
+ */
+
+ if (!(p = pp.hdrbuf) && !(p = pp.hdrbuf = newof(0, char, MAXTOKEN, 0)))
+ error(3, "out of space");
+ pp.state &= ~NOSPACE;
+ while ((c = pplex()) && c != '>')
+ {
+ v = p + 1;
+ STRCOPY(p, pp.token, s);
+ if (p == v && *(p - 1) == ' ' && pp.in->type != IN_MACRO)
+ p--;
+ }
+ pp.state |= NOSPACE;
+ *p++ = 0;
+ memcpy(pp.token, pp.hdrbuf, p - pp.hdrbuf);
+ c = T_HEADER;
+ goto header;
+ default:
+ error(2, "#%s: \"...\" or <...> argument expected", dirname(INCLUDE));
+ goto eatdirective;
+ }
+ goto enddirective;
+ case 0:
+ {
+ regmatch_t match[10];
+
+ /*UNDENT*/
+ p = pp.valbuf;
+ *p++ = '#';
+ STRCOPY(p, pp.token, s);
+ p0 = p;
+ pp.mode |= EXPOSE;
+ pp.state |= HEADER;
+ p6 = getline(p, &pp.valbuf[MAXTOKEN], 0);
+ pp.state &= ~HEADER;
+ pp.mode &= ~EXPOSE;
+ if (!p6)
+ {
+ *p0 = 0;
+ error(2, "%s: directive too long", pp.valbuf);
+ c = 0;
+ goto eatdirective;
+ }
+ p1 = p2 = p3 = p4 = 0;
+ p5 = *p ? p + 1 : 0;
+ checkmap:
+ i0 = *p0;
+ p = pp.valbuf;
+ var.best = 0;
+ n = 0;
+ for (map = (struct map*)pp.maps; map; map = map->next)
+ if (!(i1 = regexec(&map->re, p, elementsof(match), match, 0)))
+ {
+ if ((c = match[0].rm_eo - match[0].rm_so) > n)
+ {
+ n = c;
+ var.best = map;
+ }
+ }
+ else if (i1 != REG_NOMATCH)
+ regfatal(&map->re, 3, i1);
+ c = '\n';
+ if (map = var.best)
+ {
+ if ((pp.state & (STRICT|WARN)) && !(pp.mode & (HOSTED|RELAX)))
+ {
+ *p0 = 0;
+ if (!(pp.state & WARN) || strcmp(p + 1, dirname(PRAGMA)))
+ error(1, "%s: non-standard directive", p);
+ *p0 = i0;
+ }
+ if (!(*pp.control & SKIP))
+ {
+ n = 0;
+ for (edit = map->edit; edit; edit = edit->next)
+ if (!(i0 = regexec(&edit->re, p, elementsof(match), match, 0)))
+ {
+ n++;
+ if (i0 = regsubexec(&edit->re, p, elementsof(match), match))
+ regfatal(&edit->re, 3, i0);
+ p = edit->re.re_sub->re_buf;
+ if (edit->re.re_sub->re_flags & REG_SUB_STOP)
+ break;
+ }
+ else if (i0 != REG_NOMATCH)
+ regfatal(&edit->re, 3, i0);
+ if (n && *p)
+ {
+ p1 = s = oldof(0, char, 0, strlen(p) + 32);
+ while (*s = *p++) s++;
+ debug((-4, "map: %s", p1));
+ *s++ = '\n';
+ *s = 0;
+ error_info.line++;
+ PUSH_RESCAN(p1);
+ error_info.line--;
+ directive = LINE;
+ }
+ }
+ goto donedirective;
+ }
+ if (directive != PRAGMA && (!(*pp.control & SKIP) || !(pp.mode & (HOSTED|RELAX))))
+ {
+ *p0 = 0;
+ error(1, "%s: unknown directive", pptokstr(pp.valbuf, 0));
+ *p0 = i0;
+ }
+ pass:
+ if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT) && (directive == PRAGMA || !(pp.mode & INIT)))
+ {
+ *p0 = 0;
+ if (p2) *p2 = 0;
+ if (p4)
+ {
+ if (p4 == p5)
+ {
+ p5 = strcpy(pp.tmpbuf, p5);
+ if (p = strchr(p5, MARK))
+ {
+ s = p;
+ while (*p)
+ if ((*s++ = *p++) == MARK && *p == MARK) p++;
+ *s = 0;
+ }
+ }
+ *p4 = 0;
+ }
+ if (p = (char*)memchr(pp.valbuf + 1, MARK, p6 - pp.valbuf - 1))
+ {
+ s = p;
+ while (p < p6) switch (*s++ = *p++)
+ {
+ case 0:
+ s = p;
+ break;
+ case MARK:
+ p++;
+ break;
+ }
+ *s = 0;
+ }
+ (*pp.pragma)(pp.valbuf + 1, p1, p3, p5, (pp.state & COMPILE) || (pp.mode & INIT) != 0);
+ emitted = 1;
+ }
+ goto donedirective;
+
+ /*INDENT*/
+ }
+ }
+ if (*pp.control & SKIP) goto eatdirective;
+ switch (directive)
+ {
+#if MACDEF
+ case ENDMAC:
+ c = pplex();
+ error(2, "no matching #%s for #%s", dirname(MACDEF), dirname(ENDMAC));
+ goto enddirective;
+#endif
+#if MACDEF
+ case MACDEF:
+ if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: non-standard directive", pp.token);
+ /*FALLTHROUGH*/
+#endif
+ case DEFINE:
+ n2 = error_info.line;
+ if ((c = pplex()) == '#' && directive == DEFINE)
+ goto assertion;
+ if (c == '<')
+ {
+ n = 1;
+ c = pplex();
+ }
+ else
+ n = 0;
+ if (!(sym = macsym(c)))
+ goto eatdirective;
+ if (pp.truncate)
+ ppfsm(FSM_MACRO, pp.token);
+ mac = sym->macro;
+ if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev && mac->value)
+ goto eatdirective;
+ if (n)
+ goto tuple;
+ old = *mac;
+ i0 = sym->flags;
+ sym->flags &= ~(SYM_BUILTIN|SYM_EMPTY|SYM_FINAL|SYM_FUNCTION|SYM_INIT|SYM_INITIAL|SYM_MULTILINE|SYM_NOEXPAND|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
+#if MACDEF
+ if (directive == MACDEF)
+ sym->flags |= SYM_MULTILINE;
+#endif
+ mac->arity = 0;
+ mac->formals = 0;
+ mac->value = 0;
+ pp.state &= ~NOSPACE;
+ pp.state |= DEFINITION|NOEXPAND;
+ switch (c = pplex())
+ {
+ case '(':
+ sym->flags |= SYM_FUNCTION;
+ pp.state |= NOSPACE;
+#if MACKEYARGS
+ if (pp.option & KEYARGS)
+ {
+ n = 2 * MAXTOKEN;
+ p = mac->formals = oldof(0, char, 0, n);
+ if ((c = pplex()) == T_ID) for (;;)
+ {
+ if (mac->arity < MAXFORMALS)
+ {
+ if (mac->arity) p++;
+ formargs[mac->arity] = p;
+ STRAPP(p, pp.token, s);
+ formvals[mac->arity++] = p1 = p;
+ if (mac->arity == 1) *p++ = ' ';
+ *p++ = ' ';
+ *p = 0;
+ }
+ else error(2, "%s: formal argument %s ignored", sym->name, pp.token);
+ switch (c = pplex())
+ {
+ case '=':
+ c = pplex();
+ break;
+ case ',':
+ break;
+ default:
+ goto endformals;
+ }
+ pp.state &= ~NOSPACE;
+ p0 = 0;
+ for (;;)
+ {
+ switch (c)
+ {
+ case '\n':
+ goto endformals;
+ case '(':
+ p0++;
+ break;
+ case ')':
+ if (!p0--)
+ {
+ if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0;
+ goto endformals;
+ }
+ break;
+ case ',':
+ if (!p0)
+ {
+ if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0;
+ goto nextformal;
+ }
+ break;
+ case ' ':
+ if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') continue;
+ break;
+ }
+ STRCOPY(p, pp.token, s);
+ if (p > &mac->formals[n - MAXTOKEN] && (s = newof(mac->formals, char, n += MAXTOKEN, 0)) != mac->formals)
+ {
+ n1 = s - mac->formals;
+ for (n = 0; n < mac->arity; n++)
+ {
+ formargs[n] += n1;
+ formvals[n] += n1;
+ }
+ c = p - mac->formals;
+ mac->formals = s;
+ p = mac->formals + c;
+ }
+ c = pplex();
+ }
+ nextformal:
+ pp.state |= NOSPACE;
+ if ((c = pplex()) != T_ID)
+ {
+ c = ',';
+ break;
+ }
+ }
+ endformals: /*NOP*/;
+ }
+ else
+#endif
+ {
+ p = mac->formals = oldof(0, char, 0, MAXFORMALS * (MAXID + 1));
+ c = pplex();
+#if COMPATIBLE
+ if ((pp.state & COMPATIBILITY) && c == ',')
+ {
+ if ((pp.state & WARN) && !(pp.mode & HOSTED))
+ error(1, "%s: macro formal argument expected", sym->name);
+ while ((c = pplex()) == ',');
+ }
+#endif
+ for (;;)
+ {
+ if (c == T_VARIADIC)
+ {
+ if (sym->flags & SYM_VARIADIC)
+ error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token);
+ sym->flags |= SYM_VARIADIC;
+ v = __va_args__;
+ }
+ else if (c == T_ID)
+ {
+ v = pp.token;
+ if (sym->flags & SYM_VARIADIC)
+ error(2, "%s: %s: macro formal argument cannot follow ...", sym->name, v);
+ else if (streq(v, __va_args__))
+ error(2, "%s: %s: invalid macro formal argument", sym->name, v);
+ }
+ else
+ break;
+ if (mac->arity < MAXFORMALS)
+ {
+ for (n = 0; n < mac->arity; n++)
+ if (streq(formargs[n], v))
+ error(2, "%s: %s: duplicate macro formal argument", sym->name, v);
+ formargs[mac->arity++] = p;
+ STRAPP(p, v, s);
+ }
+ else
+ error(2, "%s: %s: macro formal argument ignored", sym->name, v);
+ if ((c = pplex()) == ',')
+ {
+ c = pplex();
+#if COMPATIBLE
+ if ((pp.state & COMPATIBILITY) && c == ',')
+ {
+ if ((pp.state & WARN) && !(pp.mode & HOSTED))
+ error(1, "%s: macro formal argument expected", sym->name);
+ while ((c = pplex()) == ',');
+ }
+#endif
+ }
+ else if (c != T_VARIADIC)
+ break;
+ else
+ {
+ if (sym->flags & SYM_VARIADIC)
+ error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token);
+ sym->flags |= SYM_VARIADIC;
+ c = pplex();
+ break;
+ }
+ }
+ if (mac->arity && (s = newof(mac->formals, char, p - mac->formals, 0)) != mac->formals)
+ {
+ n1 = s - mac->formals;
+ for (n = 0; n < mac->arity; n++)
+ formargs[n] += n1;
+ mac->formals = s;
+ }
+ }
+ if (!mac->arity)
+ {
+ free(mac->formals);
+ mac->formals = 0;
+ }
+ switch (c)
+ {
+ case ')':
+#if MACKEYARGS
+ pp.state |= NOEXPAND|NOSPACE;
+#else
+ pp.state |= NOEXPAND;
+#endif
+ c = pplex();
+ break;
+ default:
+ error(2, "%s: invalid macro formal argument list", sym->name);
+ if (mac->formals)
+ {
+ free(mac->formals);
+ mac->formals = 0;
+ mac->arity = 0;
+ }
+ free(mac);
+ sym->macro = 0;
+ goto eatdirective;
+ }
+ pp.state &= ~NOSPACE;
+ break;
+ case ' ':
+ case '\t':
+ c = pplex();
+ break;
+ }
+ n = 2 * MAXTOKEN;
+#if MACKEYARGS
+ p1 = p;
+#endif
+ p = mac->value = oldof(0, char, 0, n);
+ var.type = 0;
+ n1 = 0;
+#if MACDEF
+ i2 = i3 = 0;
+ n3 = pp.state;
+#endif
+ if ((pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
+ switch (c)
+ {
+ case '+':
+ case '-':
+ case '&':
+ case '|':
+ case '<':
+ case '>':
+ case ':':
+ case '=':
+ *p++ = ' ';
+ break;
+ }
+ o = 0;
+ for (;;)
+ {
+ switch (c)
+ {
+ case T_ID:
+ for (c = 0; c < mac->arity; c++)
+ if (streq(formargs[c], pp.token))
+ {
+#if COMPATIBLE
+ if (!(pp.state & COMPATIBILITY))
+#endif
+ if (var.type != TOK_TOKCAT && p > mac->value && *(p - 1) != ' ' && !(pp.option & PRESERVE)) *p++ = ' ';
+ *p++ = MARK;
+#if COMPATIBLE
+ if ((pp.state & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) *p++ = 'C';
+ else
+#endif
+ *p++ = (n1 || var.type == TOK_TOKCAT) ? 'C' : 'A';
+ *p++ = c + ARGOFFSET;
+ var.type = TOK_FORMAL|TOK_ID;
+ c = '>';
+ goto checkvalue;
+ }
+ if (var.type == TOK_BUILTIN) switch ((int)hashget(pp.strtab, pp.token))
+ {
+ case V_DEFAULT:
+ case V_EMPTY:
+ sym->flags |= SYM_EMPTY;
+ break;
+ }
+ else if (pp.hiding && (var.symbol = ppsymref(pp.symtab, pp.token)) && var.symbol->hidden)
+ {
+ for (var.inp = pp.in; var.inp->type != IN_FILE && var.inp->prev; var.inp = var.inp->prev);
+ p += sfsprintf(p, MAXTOKEN, "_%d_%s_hIDe", var.inp->hide, pp.token);
+ var.type = TOK_ID;
+ goto checkvalue;
+ }
+ var.type = TOK_ID;
+ break;
+ case '#':
+ var.type = 0;
+#if MACDEF
+ if (!(sym->flags & (SYM_FUNCTION|SYM_MULTILINE))) break;
+#else
+ if (!(sym->flags & SYM_FUNCTION)) break;
+#endif
+ pp.state |= NOSPACE;
+ c = pplex();
+ if (c == '@')
+ {
+ c = pplex();
+ i4 = 'S';
+ }
+ else i4 = 'Q';
+ pp.state &= ~NOSPACE;
+ if (c != T_ID) c = mac->arity;
+ else for (c = 0; c < mac->arity; c++)
+ if (streq(formargs[c], pp.token))
+ break;
+ if (c >= mac->arity)
+ {
+#if MACDEF
+ if (sym->flags & SYM_MULTILINE)
+ {
+ if (n3 & NEWLINE)
+ {
+ pp.state &= ~NOEXPAND;
+ switch ((int)hashref(pp.dirtab, pp.token))
+ {
+ case ENDMAC:
+ if (!i2--) goto gotdefinition;
+ break;
+ case INCLUDE:
+ /* PARSE HEADER constant */
+ break;
+ case MACDEF:
+ i2++;
+ break;
+ }
+ *p++ = '#';
+ }
+ }
+ else
+#endif
+#if COMPATIBLE
+ if (pp.state & COMPATIBILITY) *p++ = '#';
+ else
+#endif
+ error(2, "# must precede a formal parameter");
+ }
+ else
+ {
+ if (p > mac->value && ppisidig(*(p - 1)) && !(pp.option & PRESERVE)) *p++ = ' ';
+ *p++ = MARK;
+ *p++ = i4;
+ *p++ = c + ARGOFFSET;
+ goto checkvalue;
+ }
+ break;
+ case T_TOKCAT:
+ if (p <= mac->value) error(2, "%s lhs operand omitted", pp.token);
+ else
+ {
+ if (*(p - 1) == ' ') p--;
+ if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C';
+ }
+ pp.state |= NOSPACE;
+ c = pplex();
+ pp.state &= ~NOSPACE;
+ if (c == '\n') error(2, "%s rhs operand omitted", pptokchr(T_TOKCAT));
+ var.type = TOK_TOKCAT;
+ continue;
+ case '(':
+ if (*pp.token == '#')
+ {
+ var.type = TOK_BUILTIN;
+ n1++;
+ }
+ else
+ {
+ var.type = 0;
+ if (n1) n1++;
+ }
+ break;
+ case ')':
+ var.type = 0;
+ if (n1) n1--;
+ break;
+ case T_STRING:
+ case T_CHARCONST:
+ pp.state &= ~NOEXPAND;
+ var.type = 0;
+ if (strchr(pp.token, MARK)) pp.state &= ~NOEXPAND;
+#if COMPATIBLE
+ /*UNDENT*/
+
+ if ((sym->flags & SYM_FUNCTION) && (pp.state & (COMPATIBILITY|TRANSITION)))
+ {
+ char* v;
+
+ s = pp.token;
+ for (;;)
+ {
+ if (!*s) goto checkvalue;
+ if (ppisid(*s))
+ {
+ v = s;
+ while (ppisid(*++s));
+ i1 = *s;
+ *s = 0;
+ for (c = 0; c < mac->arity; c++)
+ if (streq(formargs[c], v))
+ {
+ *p++ = MARK;
+ *p++ = 'C';
+ *p++ = c + ARGOFFSET;
+ if (!(pp.mode & HOSTED) && (!(pp.state & COMPATIBILITY) || (pp.state & WARN))) switch (*pp.token)
+ {
+ case '"':
+ error(1, "use the # operator to \"...\" quote macro arguments");
+ break;
+ case '\'':
+ error(1, "macro arguments should be '...' quoted before substitution");
+ break;
+ }
+ goto quotearg;
+ }
+ STRCOPY2(p, v);
+ quotearg:
+ *s = i1;
+ }
+ else *p++ = *s++;
+ }
+ }
+ /*INDENT*/
+#endif
+ break;
+ case '\n':
+#if MACDEF
+ if (sym->flags & SYM_MULTILINE)
+ {
+ if (pp.state & EOF2NL)
+ {
+ error_info.line++;
+ pp.state |= HIDDEN;
+ pp.hidden++;
+ var.type = 0;
+ if (!i3++)
+ goto checkvalue;
+ break;
+ }
+ pp.state |= EOF2NL;
+ error(2, "%s: missing #%s", sym->name, dirname(ENDMAC));
+ }
+#endif
+ goto gotdefinition;
+ case 0:
+ c = '\n';
+ goto gotdefinition;
+#if COMPATIBLE
+ case ' ':
+ if (pp.state & COMPATIBILITY) var.type = 0;
+ if (pp.option & PRESERVE) break;
+ if (p > mac->value && *(p - 1) != ' ') *p++ = ' ';
+ goto checkvalue;
+ case '\t':
+ if (var.type & TOK_ID)
+ {
+ while ((c = pplex()) == '\t');
+ if (c == T_ID)
+ {
+ if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C';
+ var.type = TOK_TOKCAT;
+ if (pp.state & WARN) error(1, "use the ## operator to concatenate macro arguments");
+ }
+ else var.type = 0;
+ continue;
+ }
+ var.type = 0;
+ if (pp.option & PRESERVE) break;
+ if (p > mac->value && *(p - 1) != ' ') *p++ = ' ';
+ goto checkvalue;
+#endif
+ case MARK:
+ pp.state &= ~NOEXPAND;
+ /*FALLTHROUGH*/
+
+ default:
+ var.type = 0;
+ break;
+ }
+ STRCOPY(p, pp.token, s);
+ checkvalue:
+ o = c;
+ if (p > &mac->value[n - MAXTOKEN] && (s = newof(mac->value, char, n += MAXTOKEN, 0)) != mac->value)
+ {
+ c = p - mac->value;
+ mac->value = s;
+ p = mac->value + c;
+ }
+#if MACDEF
+ n3 = pp.state;
+#endif
+ c = pplex();
+ }
+ gotdefinition:
+ while (p > mac->value && *(p - 1) == ' ') p--;
+ if (p > mac->value && (pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
+ switch (o)
+ {
+ case '+':
+ case '-':
+ case '&':
+ case '|':
+ case '<':
+ case '>':
+ case ':':
+ case '=':
+ *p++ = ' ';
+ break;
+ }
+ *p = 0;
+#if MACKEYARGS
+ if (!mac->arity) /* ok */;
+ else if (pp.option & KEYARGS)
+ {
+ p0 = mac->formals;
+ mac->formkeys = newof(0, struct ppkeyarg, n, p1 - p0 + 1);
+ s = (char*)&mac->formkeys[mac->arity];
+ (void)memcpy(s, p0, p1 - p0 + 1);
+ free(p0);
+ for (n = 0; n < mac->arity; n++)
+ {
+ mac->formkeys[n].name = s + (formargs[n] - p0);
+ mac->formkeys[n].value = s + (formvals[n] - p0);
+ }
+ }
+ else
+#endif
+ for (n = 1; n < mac->arity; n++)
+ *(formargs[n] - 1) = ',';
+ if (old.value)
+ {
+ if ((i0 & SYM_FUNCTION) != (sym->flags & SYM_FUNCTION) || old.arity != mac->arity || !streq(old.value, mac->value)) goto redefined;
+ if (!old.formals)
+ {
+ if (mac->formals) goto redefined;
+ }
+ else if (mac->formals)
+ {
+#if MACKEYARGS
+ if (pp.option & KEYARGS)
+ {
+ for (n = 0; n < mac->arity; n++)
+ if (!streq(mac->formkeys[n].name, old.formkeys[n].name) || !streq(mac->formkeys[n].value, old.formkeys[n].value))
+ goto redefined;
+ }
+ else
+#endif
+ if (!streq(mac->formals, old.formals)) goto redefined;
+ }
+#if MACKEYARGS
+ if (pp.option & KEYARGS)
+ {
+ if (mac->formkeys) free(mac->formkeys);
+ mac->formkeys = old.formkeys;
+ }
+ else
+#endif
+ {
+ if (mac->formals) free(mac->formals);
+ mac->formals = old.formals;
+ }
+ free(mac->value);
+ mac->value = old.value;
+ goto benign;
+ redefined:
+ if (!(pp.mode & HOSTED) || !(i0 & SYM_INITIAL))
+ error(1, "%s redefined", sym->name);
+#if MACKEYARGS
+ if ((pp.option & KEYARGS) && mac->formkeys)
+ free(mac->formkeys);
+#endif
+#if MACKEYARGS
+ if (!(pp.option & KEYARGS))
+#endif
+ if (old.formals) free(old.formals);
+ free(old.value);
+ }
+ else if (!pp.truncate) ppfsm(FSM_MACRO, sym->name);
+ mac->value = newof(mac->value, char, (mac->size = p - mac->value) + 1, 0);
+ if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT)))
+ {
+ ppsync();
+ ppprintf("#%s %s", dirname(DEFINE), sym->name);
+ if (sym->flags & SYM_FUNCTION)
+ {
+ ppputchar('(');
+ if (mac->formals)
+ ppprintf("%s", mac->formals);
+ ppputchar(')');
+ }
+ if ((p = mac->value) && *p)
+ {
+ ppputchar(' ');
+ i0 = 0;
+ while (n = *p++)
+ {
+ if (n != MARK || (n = *p++) == MARK)
+ {
+ ppputchar(n);
+ i0 = ppisid(n);
+ }
+ else
+ {
+ if (n == 'Q')
+ ppputchar('#');
+ else if (i0)
+ {
+ ppputchar('#');
+ ppputchar('#');
+ }
+ s = formargs[*p++ - ARGOFFSET];
+ while ((n = *s++) && n != ',')
+ ppputchar(n);
+ if (ppisid(*p) || *p == MARK)
+ {
+ ppputchar('#');
+ ppputchar('#');
+ }
+ i0 = 0;
+ }
+ ppcheckout();
+ }
+ }
+ emitted = 1;
+ }
+ benign:
+ if (pp.mode & BUILTIN) sym->flags |= SYM_BUILTIN;
+ if (pp.option & FINAL) sym->flags |= SYM_FINAL;
+ if (pp.mode & INIT) sym->flags |= SYM_INIT;
+ if (pp.option & INITIAL) sym->flags |= SYM_INITIAL;
+ if (pp.state & NOEXPAND) sym->flags |= SYM_NOEXPAND;
+ if (pp.option & PREDEFINED) sym->flags |= SYM_PREDEFINED;
+ if (pp.mode & READONLY) sym->flags |= SYM_READONLY;
+ if (pp.macref) (*pp.macref)(sym, error_info.file, n2, mac ? error_info.line - n2 + 1 : REF_UNDEF, mac ? strsum(mac->value, (long)mac->arity) : 0L);
+ break;
+ assertion:
+ c = pplex();
+ if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s #%s: assertions are non-standard", dirname(directive), pptokstr(pp.token, 0));
+ if (c != T_ID)
+ {
+ error(2, "%s: invalid predicate name", pptokstr(pp.token, 0));
+ goto eatdirective;
+ }
+ switch ((int)hashref(pp.strtab, pp.token))
+ {
+ case X_DEFINED:
+ case X_EXISTS:
+ case X_STRCMP:
+ error(2, "%s is a builtin predicate", pp.token);
+ goto eatdirective;
+ case X_SIZEOF:
+ error(2, "%s cannot be a predicate", pp.token);
+ goto eatdirective;
+ }
+ strcpy(pp.tmpbuf, pp.token);
+ switch (pppredargs())
+ {
+ case T_ID:
+ case T_STRING:
+ assert(directive, pp.tmpbuf, pp.args);
+ break;
+ case 0:
+ assert(directive, pp.tmpbuf, NiL);
+ break;
+ default:
+ error(2, "invalid predicate argument list");
+ goto eatdirective;
+ }
+ break;
+ tuple:
+ pp.state |= DEFINITION|NOEXPAND|NOSPACE;
+ rp = 0;
+ tp = mac->tuple;
+ if (!tp && !mac->value)
+ ppfsm(FSM_MACRO, sym->name);
+ while ((c = pplex()) && c != '>' && c != '\n')
+ {
+ for (; tp; tp = tp->nomatch)
+ if (streq(tp->token, pp.token))
+ break;
+ if (!tp)
+ {
+ if (!(tp = newof(0, struct pptuple, 1, strlen(pp.token))))
+ error(3, "out of space");
+ strcpy(tp->token, pp.token);
+ if (rp)
+ {
+ tp->nomatch = rp;
+ rp->nomatch = tp;
+ }
+ else
+ {
+ tp->nomatch = mac->tuple;
+ mac->tuple = tp;
+ }
+ }
+ rp = tp;
+ tp = tp->match;
+ }
+ pp.state &= ~NOSPACE;
+ if (!rp || c != '>')
+ error(2, "%s: > omitted in tuple macro definition", sym->name);
+ else
+ {
+ n = 2 * MAXTOKEN;
+ p = v = oldof(0, char, 0, n);
+ while ((c = pplex()) && c != '\n')
+ if (p > v || c != ' ')
+ {
+ STRCOPY(p, pp.token, s);
+ if (p > &v[n - MAXTOKEN] && (s = newof(v, char, n += MAXTOKEN, 0)) != v)
+ {
+ c = p - v;
+ v = s;
+ p = v + c;
+ }
+ }
+ while (p > v && *(p - 1) == ' ')
+ p--;
+ n = p - v;
+ tp = newof(0, struct pptuple, 1, n);
+ strcpy(tp->token, v);
+ tp->match = rp->match;
+ rp->match = tp;
+ }
+ goto benign;
+ case WARNING:
+ if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: non-standard directive", pp.token);
+ /*FALLTHROUGH*/
+ case ERROR:
+ pp.state &= ~DISABLE;
+ p = pp.tmpbuf;
+ while ((c = pplex()) != '\n')
+ if (p + strlen(pp.token) < &pp.tmpbuf[MAXTOKEN])
+ {
+ STRCOPY(p, pp.token, s);
+ pp.state &= ~NOSPACE;
+ }
+ *p = 0;
+ p = *pp.tmpbuf ? pp.tmpbuf : ((directive == WARNING) ? "user warning" : "user error");
+ n = (directive == WARNING) ? 1 : 3;
+ error(n, "%s", p);
+ break;
+ case LET:
+ n2 = error_info.line;
+ if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: non-standard directive", pp.token);
+ if (!(sym = macsym(c = pplex()))) goto eatdirective;
+ if ((c = pplex()) != '=')
+ {
+ error(2, "%s: = expected", sym->name);
+ goto eatdirective;
+ }
+ sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_MULTILINE|SYM_PREDEFINED|SYM_VARIADIC);
+ mac = sym->macro;
+ mac->arity = 0;
+ if (mac->value)
+ {
+ if (!(sym->flags & SYM_REDEFINE) && !sym->hidden)
+ error(1, "%s: redefined", sym->name);
+#if MACKEYARGS
+ if ((pp.option & KEYARGS) && mac->formkeys) free(mac->formkeys);
+ else
+#endif
+ free(mac->formals);
+ mac->formals = 0;
+ n = strlen(mac->value) + 1;
+ }
+ else
+ {
+ ppfsm(FSM_MACRO, sym->name);
+ n = 0;
+ }
+ n1 = ppexpr(&i1);
+ if (i1) c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%luU", n1);
+ else c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%ld", n1);
+ if (n < ++c)
+ {
+ if (mac->value) free(mac->value);
+ mac->value = oldof(0, char, 0, c);
+ }
+ strcpy(mac->value, pp.tmpbuf);
+ sym->flags |= SYM_REDEFINE;
+ c = (pp.state & NEWLINE) ? '\n' : ' ';
+ goto benign;
+ case LINE:
+ pp.state &= ~DISABLE;
+ if ((c = pplex()) == '#')
+ {
+ c = pplex();
+ directive = INCLUDE;
+ }
+ if (c != T_DECIMAL && c != T_OCTAL)
+ {
+ error(1, "#%s: line number expected", dirname(LINE));
+ goto eatdirective;
+ }
+ linesync:
+ n = error_info.line;
+ error_info.line = strtol(pp.token, NiL, 0);
+ if (error_info.line == 0 && directive == LINE && (pp.state & STRICT) && !(pp.mode & HOSTED))
+ error(1, "#%s: line number should be > 0", dirname(LINE));
+ pp.state &= ~DISABLE;
+ pp.state |= STRIP;
+ switch (c = pplex())
+ {
+ case T_STRING:
+ s = error_info.file;
+ if (*(p = pp.token)) pathcanon(p, 0);
+ fp = ppsetfile(p);
+ error_info.file = fp->name;
+ if (error_info.line == 1)
+ ppmultiple(fp, INC_TEST);
+ switch (c = pplex())
+ {
+ case '\n':
+ break;
+ case T_DECIMAL:
+ case T_OCTAL:
+ if (directive == LINE && (pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: integer file type argument is non-standard", dirname(LINE));
+ break;
+ default:
+ error(1, "#%s: integer file type argument expected", dirname(LINE));
+ break;
+ }
+ if (directive == LINE) pp.in->flags &= ~IN_ignoreline;
+ else if (pp.incref)
+ {
+ if (error_info.file != s)
+ {
+ switch (*pp.token)
+ {
+ case PP_sync_push:
+ if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
+ else (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH);
+ break;
+ case PP_sync_pop:
+ if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
+ else (*pp.incref)(s, error_info.file, n - 1, PP_SYNC_POP);
+ break;
+ case PP_sync_ignore:
+ if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
+ else
+ {
+ (*pp.incref)(s, error_info.file, n, PP_SYNC_IGNORE);
+ error_info.file = s;
+ }
+ break;
+ default:
+ if (*s)
+ {
+ if (fp == pp.insert)
+ pp.insert = 0;
+ else if (error_info.line == 1 && !pp.insert)
+ (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH);
+ else
+ {
+ if (!pp.insert) pp.insert = ppgetfile(s);
+ (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT);
+ }
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case '\n':
+ break;
+ default:
+ error(1, "#%s: \"file-name\" expected", dirname(LINE));
+ break;
+ }
+ if (directive == LINE && (pp.in->flags & IN_ignoreline))
+ error_info.line = n + 1;
+ else
+ {
+ pp.hidden = 0;
+ pp.state &= ~HIDDEN;
+ if (pp.linesync)
+ {
+#if CATSTRINGS
+ if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE;
+ else
+#endif
+ {
+ s = pp.lineid;
+ n = pp.flags;
+ if (directive == LINE)
+ {
+ pp.flags &= ~PP_linetype;
+ if (pp.macref) pp.lineid = dirname(LINE);
+ }
+ (*pp.linesync)(error_info.line, error_info.file);
+ pp.flags = n;
+ pp.lineid = s;
+ }
+ }
+ }
+ directive = LINE;
+ break;
+ case PRAGMA:
+ /*
+ * #pragma [STDC] [pass:] [no]option [arg ...]
+ *
+ * pragma args are not expanded by default
+ *
+ * if STDC is present then it is silently passed on
+ *
+ * if pass is pp.pass then the option is used
+ * and verified but is not passed on
+ *
+ * if pass is omitted then the option is passed on
+ *
+ * otherwise if pass is non-null and not pp.pass then
+ * the option is passed on but not used
+ *
+ * if the line does not match this form then
+ * it is passed on unchanged
+ *
+ * #directive pass: option [...]
+ * ^ ^ ^ ^ ^ ^ ^ ^
+ * pp.valbuf p0 p1 p2 p3 p4 p5 p6
+ *
+ * p? 0 if component omitted
+ * i0 0 if ``no''option
+ */
+
+ p = pp.valbuf;
+ *p++ = '#';
+ STRCOPY(p, pp.token, s);
+ p0 = p;
+ if (pp.option & PRAGMAEXPAND)
+ pp.state &= ~DISABLE;
+ if (!(p6 = getline(p, &pp.valbuf[MAXTOKEN], !!(pp.option & PRAGMAEXPAND))))
+ {
+ *p0 = 0;
+ error(2, "%s: directive too long", pp.valbuf);
+ c = 0;
+ goto eatdirective;
+ }
+ p1 = ++p;
+ while (ppisid(*p))
+ p++;
+ if (p == p1)
+ {
+ p5 = p;
+ p4 = 0;
+ p3 = 0;
+ p2 = 0;
+ p1 = 0;
+ }
+ else if (*p != ':')
+ {
+ p5 = *p ? p + (*p == ' ') : 0;
+ p4 = p;
+ p3 = p1;
+ p2 = 0;
+ p1 = 0;
+ }
+ else
+ {
+ p2 = p++;
+ p3 = p;
+ while (ppisid(*p))
+ p++;
+ if (p == p3)
+ {
+ p4 = p1;
+ p3 = 0;
+ p2 = 0;
+ p1 = 0;
+ }
+ else
+ p4 = p;
+ p5 = *p4 ? p4 + (*p4 == ' ') : 0;
+ }
+ if (!p1 && p3 && (p4 - p3) == 4 && strneq(p3, "STDC", 4))
+ goto pass;
+ if ((pp.state & WARN) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: non-standard directive", dirname(PRAGMA));
+ i0 = !p3 || *p3 != 'n' || *(p3 + 1) != 'o';
+ if (!p3)
+ goto checkmap;
+ if (p1)
+ {
+ *p2 = 0;
+ n = streq(p1, pp.pass);
+ *p2 = ':';
+ if (!n)
+ goto checkmap;
+ }
+ else
+ n = 0;
+ i2 = *p4;
+ *p4 = 0;
+ if (((i1 = (int)hashref(pp.strtab, p3 + (i0 ? 0 : 2))) < 1 || i1 > X_last_option) && (i0 || (i1 = (int)hashref(pp.strtab, p3)) > X_last_option))
+ i1 = 0;
+ if ((pp.state & (COMPATIBILITY|STRICT)) == STRICT && !(pp.mode & (HOSTED|RELAX)))
+ {
+ if (pp.optflags[i1] & OPT_GLOBAL)
+ goto donedirective;
+ if (n || (pp.mode & WARN))
+ {
+ n = 0;
+ error(1, "#%s: non-standard directive ignored", dirname(PRAGMA));
+ }
+ i1 = 0;
+ }
+ if (!n)
+ {
+ if (!(pp.optflags[i1] & OPT_GLOBAL))
+ {
+ *p4 = i2;
+ goto checkmap;
+ }
+ if (!(pp.optflags[i1] & OPT_PASS))
+ n = 1;
+ }
+ else if (!i1)
+ error(2, "%s: unknown option", p1);
+ else if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "%s: non-standard option", p1);
+ p = p5;
+ switch (i1)
+ {
+ case X_ALLMULTIPLE:
+ ppop(PP_MULTIPLE, i0);
+ break;
+ case X_ALLPOSSIBLE:
+ setoption(ALLPOSSIBLE, i0);
+ break;
+ case X_BUILTIN:
+ setmode(BUILTIN, i0);
+ break;
+ case X_CATLITERAL:
+ setmode(CATLITERAL, i0);
+ if (pp.mode & CATLITERAL)
+ setoption(STRINGSPLIT, 0);
+ break;
+ case X_CDIR:
+ tokop(PP_CDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
+ break;
+ case X_CHECKPOINT:
+#if CHECKPOINT
+ ppload(p);
+#else
+ error(3, "%s: preprocessor not compiled with checkpoint enabled", p3);
+#endif
+ break;
+ case X_CHOP:
+ tokop(PP_CHOP, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
+ break;
+ case X_COMPATIBILITY:
+ ppop(PP_COMPATIBILITY, i0);
+ break;
+ case X_DEBUG:
+ error_info.trace = i0 ? (p ? -strtol(p, NiL, 0) : -1) : 0;
+ break;
+ case X_ELSEIF:
+ setoption(ELSEIF, i0);
+ break;
+ case X_EXTERNALIZE:
+ setmode(EXTERNALIZE, i0);
+ break;
+ case X_FINAL:
+ setoption(FINAL, i0);
+ break;
+ case X_HEADEREXPAND:
+ setoption(HEADEREXPAND, i0);
+ break;
+ case X_HEADEREXPANDALL:
+ setoption(HEADEREXPANDALL, i0);
+ break;
+ case X_HIDE:
+ case X_NOTE:
+ PUSH_LINE(p);
+ /* UNDENT...*/
+ while (c = pplex())
+ {
+ if (c != T_ID) error(1, "%s: %s: identifier expected", p3, pp.token);
+ else if (sym = ppsymset(pp.symtab, pp.token))
+ {
+ if (i1 == X_NOTE)
+ {
+ sym->flags &= ~SYM_NOTICED;
+ ppfsm(FSM_MACRO, sym->name);
+ }
+ else if (i0)
+ {
+ if (!sym->hidden && !(sym->hidden = newof(0, struct pphide, 1, 0)))
+ error(3, "out of space");
+ if (!sym->macro)
+ ppfsm(FSM_MACRO, sym->name);
+ if (!sym->hidden->level++)
+ {
+ pp.hiding++;
+ if (sym->macro && !(sym->flags & (SYM_ACTIVE|SYM_READONLY)))
+ {
+ sym->hidden->macro = sym->macro;
+ sym->macro = 0;
+ sym->hidden->flags = sym->flags;
+ sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
+ }
+ }
+ }
+ else if (sym->hidden)
+ {
+ if ((mac = sym->macro) && !(sym->flags & (SYM_ACTIVE|SYM_READONLY)))
+ {
+ if (mac->formals) free(mac->formals);
+ free(mac->value);
+ free(mac);
+ sym->macro = 0;
+ sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
+ }
+ if (!--sym->hidden->level)
+ {
+ pp.hiding--;
+ if (sym->hidden->macro)
+ {
+ sym->macro = sym->hidden->macro;
+ sym->flags = sym->hidden->flags;
+ }
+ free(sym->hidden);
+ sym->hidden = 0;
+ }
+ }
+ }
+ }
+ /*...INDENT*/
+ POP_LINE();
+ break;
+ case X_HOSTDIR:
+ tokop(PP_HOSTDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
+ break;
+ case X_HOSTED:
+ setmode(HOSTED, i0);
+ break;
+ case X_HOSTEDTRANSITION:
+ setmode(HOSTEDTRANSITION, i0);
+ break;
+ case X_ID:
+ tokop(PP_ID, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
+ break;
+ case X_IGNORE:
+ tokop(PP_IGNORE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
+ break;
+ case X_INCLUDE:
+ tokop(PP_INCLUDE, p3, p, i0, TOKOP_STRING|TOKOP_DUP);
+ break;
+ case X_INITIAL:
+ setoption(INITIAL, i0);
+ break;
+ case X_KEYARGS:
+ ppop(PP_KEYARGS, i0);
+ break;
+ case X_LINE:
+ if (pp.linesync) pp.olinesync = pp.linesync;
+ pp.linesync = i0 ? pp.olinesync : (PPLINESYNC)0;
+ break;
+ case X_LINEBASE:
+ ppop(PP_LINEBASE, i0);
+ break;
+ case X_LINEFILE:
+ ppop(PP_LINEFILE, i0);
+ break;
+ case X_LINEID:
+ ppop(PP_LINEID, i0 ? p : (char*)0);
+ break;
+ case X_LINETYPE:
+ ppop(PP_LINETYPE, i0 ? (p ? strtol(p, NiL, 0) : 1) : 0);
+ break;
+ case X_MACREF:
+ if (!p)
+ {
+ if (i0 && !pp.macref)
+ {
+ ppop(PP_LINETYPE, 1);
+ ppop(PP_MACREF, ppmacref);
+ }
+ else error(2, "%s: option cannot be unset", p3);
+ }
+ else if (s = strchr(p, ' '))
+ {
+ if (pp.macref && (s = strchr(p, ' ')))
+ {
+ *s++ = 0;
+ c = strtol(s, NiL, 0);
+ var.type = pp.truncate;
+ pp.truncate = PPTOKSIZ;
+ (*pp.macref)(pprefmac(p, REF_CREATE), error_info.file, error_info.line - (c == REF_NORMAL ? 2 : 1), c, (s = strchr(s, ' ')) ? strtol(s, NiL, 0) : 0L);
+ pp.truncate = var.type;
+ }
+ error_info.line -= 2;
+ }
+ break;
+ case X_MAP:
+ /*UNDENT*/
+ /*
+ * #pragma pp:map [id ...] "/from/[,/to/]" [ "/old/new/[glnu]" ... ]
+ */
+
+ if (!i0)
+ {
+ error(2, "%s: option cannot be unset", p3);
+ goto donedirective;
+ }
+ if (!p5)
+ {
+ error(2, "%s: address argument expected", p3);
+ goto donedirective;
+ }
+ PUSH_LINE(p5);
+ while ((c = pplex()) == T_ID)
+ {
+ sfsprintf(pp.tmpbuf, MAXTOKEN, "__%s__", s = pp.token);
+ if (c = (int)hashget(pp.dirtab, s))
+ {
+ hashput(pp.dirtab, 0, 0);
+ hashput(pp.dirtab, pp.tmpbuf, c);
+ }
+ if (c = (int)hashget(pp.strtab, s))
+ {
+ hashput(pp.strtab, 0, 0);
+ hashput(pp.strtab, pp.tmpbuf, c);
+ }
+ }
+ if (c != T_STRING || !*(s = pp.token))
+ {
+ if (c)
+ error(2, "%s: %s: address argument expected", p3, pptokstr(pp.token, 0));
+ goto eatmap;
+ }
+ map = newof(0, struct map, 1, 0);
+
+ /*
+ * /from/
+ */
+
+ if (i0 = regcomp(&map->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL))
+ regfatal(&map->re, 3, i0);
+ if (*(s += map->re.re_npat))
+ {
+ error(2, "%s: invalid characters after pattern: %s ", p3, s);
+ goto eatmap;
+ }
+
+ /*
+ * /old/new/[flags]
+ */
+
+ edit = 0;
+ while ((c = pplex()) == T_STRING)
+ {
+ if (!*(s = pp.token))
+ {
+ error(2, "%s: substitution argument expected", p3);
+ goto eatmap;
+ }
+ if (edit)
+ edit = edit->next = newof(0, struct edit, 1, 0);
+ else
+ edit = map->edit = newof(0, struct edit, 1, 0);
+ if (!(i0 = regcomp(&edit->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) && !(i0 = regsubcomp(&edit->re, s += edit->re.re_npat, NiL, 0, 0)))
+ s += edit->re.re_npat;
+ if (i0)
+ regfatal(&edit->re, 3, i0);
+ if (*s)
+ {
+ error(2, "%s: invalid characters after substitution: %s ", p3, s);
+ goto eatmap;
+ }
+ }
+ if (c)
+ {
+ error(2, "%s: %s: substitution argument expected", p3, pptokstr(pp.token, 0));
+ goto eatmap;
+ }
+ map->next = (struct map*)pp.maps;
+ pp.maps = (char*)map;
+ eatmap:
+ POP_LINE();
+ /*INDENT*/
+ break;
+ case X_MAPINCLUDE:
+ ppmapinclude(NiL, p5);
+ break;
+ case X_MODERN:
+ setoption(MODERN, i0);
+ break;
+ case X_MULTIPLE:
+ n = 1;
+ if (pp.in->type == IN_FILE)
+ ppmultiple(ppsetfile(error_info.file), i0 ? INC_CLEAR : INC_TEST);
+ break;
+ case X_NATIVE:
+ setoption(NATIVE, i0);
+ break;
+ case X_OPSPACE:
+ ppfsm(FSM_OPSPACE, i0 ? p4 : (char*)0);
+ break;
+ case X_PASSTHROUGH:
+ ppop(PP_PASSTHROUGH, i0);
+ break;
+ case X_PEDANTIC:
+ ppop(PP_PEDANTIC, i0);
+ break;
+ case X_PLUSCOMMENT:
+ ppop(PP_PLUSCOMMENT, i0);
+ break;
+ case X_PLUSPLUS:
+ ppop(PP_PLUSPLUS, i0);
+ break;
+ case X_PLUSSPLICE:
+ setoption(PLUSSPLICE, i0);
+ break;
+ case X_PRAGMAEXPAND:
+ setoption(PRAGMAEXPAND, i0);
+ break;
+ case X_PRAGMAFLAGS:
+ tokop(PP_PRAGMAFLAGS, p3, p, i0, 0);
+ break;
+ case X_PREDEFINED:
+ setoption(PREDEFINED, i0);
+ break;
+ case X_PREFIX:
+ setoption(PREFIX, i0);
+ break;
+ case X_PRESERVE:
+ setoption(PRESERVE, i0);
+ if (pp.option & PRESERVE)
+ {
+ setmode(CATLITERAL, 0);
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_TRANSITION, 0);
+ ppop(PP_PLUSCOMMENT, 1);
+ ppop(PP_SPACEOUT, 1);
+ setoption(STRINGSPAN, 1);
+ setoption(STRINGSPLIT, 0);
+ ppop(PP_HOSTDIR, "-", 1);
+ }
+ break;
+ case X_PROTOTYPED:
+ /*
+ * this option doesn't bump the token count
+ */
+
+ n = 1;
+ directive = ENDIF;
+#if PROTOTYPE
+ setoption(PROTOTYPED, i0);
+#else
+ error(1, "preprocessor not compiled with prototype conversion enabled");
+#endif
+ break;
+ case X_PROTO:
+ setoption(NOPROTO, !i0);
+ break;
+ case X_QUOTE:
+ tokop(PP_QUOTE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING);
+ break;
+ case X_READONLY:
+ setmode(READONLY, i0);
+ break;
+ case X_REGUARD:
+ setoption(REGUARD, i0);
+ break;
+ case X_RESERVED:
+ tokop(PP_RESERVED, p3, p, i0, 0);
+ break;
+ case X_SPACEOUT:
+ if (!(pp.state & (COMPATIBILITY|COMPILE)))
+ ppop(PP_SPACEOUT, i0);
+ break;
+ case X_SPLICECAT:
+ setoption(SPLICECAT, i0);
+ break;
+ case X_SPLICESPACE:
+ setoption(SPLICESPACE, i0);
+ break;
+ case X_STANDARD:
+ tokop(PP_STANDARD, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
+ break;
+ case X_STRICT:
+ ppop(PP_STRICT, i0);
+ break;
+ case X_STRINGSPAN:
+ setoption(STRINGSPAN, i0);
+ break;
+ case X_STRINGSPLIT:
+ setoption(STRINGSPLIT, i0);
+ if (pp.option & STRINGSPLIT)
+ setmode(CATLITERAL, 0);
+ break;
+ case X_SYSTEM_HEADER:
+ if (i0)
+ {
+ pp.mode |= HOSTED;
+ pp.flags |= PP_hosted;
+ pp.in->flags |= IN_hosted;
+ }
+ else
+ {
+ pp.mode &= ~HOSTED;
+ pp.flags &= ~PP_hosted;
+ pp.in->flags &= ~PP_hosted;
+ }
+ break;
+ case X_TEST:
+ ppop(PP_TEST, p);
+ break;
+ case X_TEXT:
+ if (!(pp.option & KEEPNOTEXT))
+ setstate(NOTEXT, !i0);
+ break;
+ case X_TRANSITION:
+ ppop(PP_TRANSITION, i0);
+ if (pp.state & TRANSITION) ppop(PP_COMPATIBILITY, i0);
+ break;
+ case X_TRUNCATE:
+ ppop(PP_TRUNCATE, i0 ? (p ? strtol(p, NiL, 0) : TRUNCLENGTH) : 0);
+ break;
+ case X_VENDOR:
+ tokop(PP_VENDOR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP);
+ break;
+ case X_VERSION:
+ if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT))
+ {
+ sfsprintf(pp.tmpbuf, MAXTOKEN, "\"%s\"", pp.version);
+ (*pp.pragma)(dirname(PRAGMA), pp.pass, p3, pp.tmpbuf, !n);
+ if (pp.linesync && !n)
+ (*pp.linesync)(error_info.line, error_info.file);
+ emitted = 1;
+ }
+ break;
+ case X_WARN:
+ ppop(PP_WARN, i0);
+ break;
+ case X_ZEOF:
+ setoption(ZEOF, i0);
+ break;
+#if DEBUG
+ case 0:
+ case X_INCLUDED:
+ case X_NOTICED:
+ case X_OPTION:
+ case X_STATEMENT:
+ break;
+ default:
+ error(PANIC, "%s: option recognized but not implemented", pp.valbuf);
+ break;
+#endif
+ }
+ *p4 = i2;
+ if (!n)
+ goto checkmap;
+ goto donedirective;
+ case RENAME:
+ if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "#%s: non-standard directive", pp.token);
+ if ((c = pplex()) != T_ID)
+ {
+ error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
+ goto eatdirective;
+ }
+ if (!(sym = pprefmac(pp.token, REF_DELETE)) || !sym->macro)
+ goto eatdirective;
+ if (sym->flags & (SYM_ACTIVE|SYM_READONLY))
+ {
+ if (!(pp.option & ALLPOSSIBLE))
+ error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active");
+ goto eatdirective;
+ }
+ if ((c = pplex()) != T_ID)
+ {
+ error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
+ goto eatdirective;
+ }
+ var.symbol = pprefmac(pp.token, REF_CREATE);
+ if (mac = var.symbol->macro)
+ {
+ if (var.symbol->flags & (SYM_ACTIVE|SYM_READONLY))
+ {
+ if (!(pp.option & ALLPOSSIBLE))
+ error(2, "%s: macro is %s", var.symbol->name, (var.symbol->flags & SYM_READONLY) ? "readonly" : "active");
+ goto eatdirective;
+ }
+ if (!(pp.mode & HOSTED) || !(var.symbol->flags & SYM_INITIAL))
+ error(1, "%s redefined", var.symbol->name);
+ if (mac->formals) free(mac->formals);
+ free(mac->value);
+ free(mac);
+ }
+ ppfsm(FSM_MACRO, var.symbol->name);
+ var.symbol->flags = sym->flags;
+ sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
+ var.symbol->macro = sym->macro;
+ sym->macro = 0;
+ break;
+ case UNDEF:
+ if ((c = pplex()) != T_ID)
+ {
+ error(1, "%s: invalid macro name", pptokstr(pp.token, 0));
+ goto eatdirective;
+ }
+ if (sym = pprefmac(pp.token, REF_DELETE))
+ {
+ if (mac = sym->macro)
+ {
+ if (sym->flags & (SYM_ACTIVE|SYM_READONLY))
+ {
+ if (!(pp.option & ALLPOSSIBLE))
+ error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active");
+ goto eatdirective;
+ }
+ if (mac->formals) free(mac->formals);
+ free(mac->value);
+ free(mac);
+ mac = sym->macro = 0;
+ }
+ if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT)))
+ {
+ ppsync();
+ ppprintf("#%s %s", dirname(UNDEF), sym->name);
+ emitted = 1;
+ }
+ sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC);
+ n2 = error_info.line;
+ goto benign;
+ }
+ else pprefmac(pp.token, REF_UNDEF);
+ break;
+#if DEBUG
+ default:
+ error(PANIC, "#%s: directive recognized but not implemented", pp.token);
+ goto eatdirective;
+#endif
+ }
+ break;
+ case '\n':
+ break;
+ default:
+ error(1, "%s: invalid directive name", pptokstr(pp.token, 0));
+ goto eatdirective;
+ }
+ enddirective:
+#if COMPATIBLE
+ if (c != '\n' && !(pp.state & COMPATIBILITY))
+#else
+ if (c != '\n')
+#endif
+ {
+ pp.state |= DISABLE|NOSPACE;
+ if ((c = pplex()) != '\n' && (pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC)
+ error(1, "%s: invalid characters after directive", pptokstr(pp.token, 0));
+ }
+ eatdirective:
+ if (c != '\n')
+ {
+ pp.state |= DISABLE;
+ while (pplex() != '\n');
+ }
+ donedirective:
+#if _HUH_2002_05_09
+ if (!(pp.state & EOF2NL))
+ error(2, "%s in directive", pptokchr(0));
+#endif
+ pp.state &= ~RESTORE;
+ pp.mode &= ~RELAX;
+ if (!(*pp.control & SKIP))
+ {
+ pp.state |= restore;
+ switch (directive)
+ {
+ case LINE:
+ return 0;
+ case INCLUDE:
+ if (pp.include)
+ {
+ error_info.line++;
+ PUSH_FILE(pp.include, n);
+ if (!pp.vendor && (pp.found->type & TYPE_VENDOR))
+ pp.vendor = 1;
+ pp.include = 0;
+ return 0;
+ }
+ if (pp.incref)
+ (*pp.incref)(error_info.file, ppgetfile(pp.path)->name, error_info.line, PP_SYNC_IGNORE);
+ else if (pp.linesync && pp.macref)
+ {
+ pp.flags |= PP_lineignore;
+ (*pp.linesync)(error_info.line, ppgetfile(pp.path)->name);
+ }
+ /*FALLTHROUGH*/
+ default:
+ pp.in->flags |= IN_tokens;
+ /*FALLTHROUGH*/
+ case ENDIF:
+ error_info.line++;
+ if (emitted)
+ {
+ ppputchar('\n');
+ ppcheckout();
+ }
+ else
+ {
+ pp.state |= HIDDEN;
+ pp.hidden++;
+ }
+ return 0;
+ }
+ }
+ pp.state |= restore|HIDDEN|SKIPCONTROL;
+ pp.hidden++;
+ pp.level++;
+ error_info.line++;
+ return 0;
+}
+
+/*
+ * grow the pp nesting control stack
+ */
+
+void
+ppnest(void)
+{
+ register struct ppinstk* ip;
+ int oz;
+ int nz;
+ long adjust;
+ long* op;
+ long* np;
+
+ oz = pp.constack;
+ op = pp.maxcon - oz + 1;
+ nz = oz * 2;
+ np = newof(op, long, nz, 0);
+ if (adjust = (np - op))
+ {
+ ip = pp.in;
+ do
+ {
+ if (ip->control)
+ ip->control += adjust;
+ } while (ip = ip->prev);
+ }
+ pp.control = np + oz;
+ pp.constack = nz;
+ pp.maxcon = np + nz - 1;
+}
diff --git a/usr/src/lib/libpp/common/ppcpp.c b/usr/src/lib/libpp/common/ppcpp.c
new file mode 100644
index 0000000000..23e3fe7541
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppcpp.c
@@ -0,0 +1,30 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * standalone preprocessor lexical analyzer
+ */
+
+#define CPP 1
+
+#include "pplex.c"
diff --git a/usr/src/lib/libpp/common/ppdata.c b/usr/src/lib/libpp/common/ppdata.c
new file mode 100644
index 0000000000..4c15eaf940
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppdata.c
@@ -0,0 +1,179 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor data
+ *
+ * intended to be a conforming implementation of the translation phases
+ * (2.1.1.2) 1,2,3,4 and 6 of the "American National Standard for
+ * Information Systems -- Programming Language -- C", ANSI X3.159-1989.
+ *
+ * STANDARD INTERPRETATION:
+ *
+ * include files are forced to preserve #if nesting levels
+ * support for this is found in the recursive description for
+ * include file processing in the translation phases
+ *
+ * ID"..." produces two tokens: {ID}{"..."}
+ * ID'...' produces two tokens: {ID}{'...'}
+ *
+ * COMPATIBILITY:
+ *
+ * only sane Reiser compatibility is implemented
+ *
+ * strange handling of `\newline', especially in directives,
+ * is not implemented
+ *
+ * dissappearing comments used as concatenation operators work
+ * only within macro bodies
+ */
+
+static const char id[] = "\n@(#)$Id: libpp (AT&T Research) 2006-11-23 $\0\n";
+
+#include "pplib.h"
+
+#ifndef IDNAME
+#define IDNAME "pp"
+#endif
+
+static char addbuf[MAXTOKEN+1]; /* ADD buffer */
+static char argsbuf[MAXTOKEN+1]; /* predicate args */
+static char catbuf[MAXTOKEN+1]; /* catenation buffer */
+static char hidebuf[MAXTOKEN+1]; /* pp:hide buffer */
+static char outbuf[2*(PPBUFSIZ+MAXTOKEN)];/* output buffer */
+static char pathbuf[MAXTOKEN+1]; /* full path of last #include */
+static char tmpbuf[MAXTOKEN+1]; /* very temporary buffer */
+static char tokbuf[2*MAXTOKEN+1]; /* token buffer */
+static char valbuf[MAXTOKEN+1]; /* builtin macro value buffer */
+
+static char optflags[X_last_option+1];/* OPT_* flags indexed by X_* */
+
+static char null[1];
+
+static struct ppinstk instack = /* input stream stack */
+{
+ &null[0] /* nextchr */
+};
+
+static struct ppdirs stddir = /* standard include directory */
+{
+ PPSTANDARD, 0, 1, INC_STANDARD, TYPE_INCLUDE|TYPE_DIRECTORY|TYPE_HOSTED
+};
+
+static struct ppdirs firstdir = /* first include directory */
+{
+ "", &stddir, 0, INC_PREFIX, TYPE_INCLUDE|TYPE_DIRECTORY
+};
+
+struct ppglobals pp =
+{
+ /* public globals */
+
+ &id[10], /* version */
+ "", /* lineid */
+ "/dev/stdout", /* outfile */
+ IDNAME, /* pass */
+ &tokbuf[0], /* token */
+ 0, /* symbol */
+
+ /* exposed for the output macros */
+
+ &outbuf[0], /* outb */
+ &outbuf[0], /* outbuf */
+ &outbuf[0], /* outp */
+ &outbuf[PPBUFSIZ], /* oute */
+ 0, /* offset */
+
+ /* public context */
+
+ &firstdir, /* lcldirs */
+ &firstdir, /* stddirs */
+ 0, /* flags */
+ 0, /* symtab */
+
+ /* private context */
+
+ 0, /* context */
+ 0, /* state */
+ ALLMULTIPLE|CATLITERAL, /* mode */
+ PREFIX, /* option */
+ 0, /* test */
+ 0, /* filedeps.sp */
+ 0, /* filedeps.flags */
+ &firstdir, /* firstdir */
+ &firstdir, /* lastdir */
+ 0, /* hide */
+ 0, /* column */
+ -1, /* pending */
+ 0, /* firstfile */
+ 0, /* lastfile */
+ 0, /* ignore */
+ 0, /* probe */
+ 0, /* filtab */
+ 0, /* prdtab */
+ 0, /* date */
+ 0, /* time */
+ 0, /* maps */
+ 0, /* ro_state */
+ 0, /* ro_mode */
+ 0, /* ro_option */
+ {0}, /* cdir */
+ {0}, /* hostdir */
+ 0, /* ppdefault */
+ 0, /* firstindex */
+ 0, /* lastindex */
+ 0, /* firstop */
+ 0, /* lastop */
+ 0, /* firsttx */
+ 0, /* lasttx */
+ 0, /* arg_file */
+ 0, /* arg_mode */
+ 0, /* arg_style */
+ 0, /* c */
+ 0, /* hosted */
+ 0, /* ignoresrc */
+ 0, /* initialized */
+ 0, /* standalone */
+ 0, /* spare_1 */
+
+ /* library private globals */
+
+ "\"08/11/94\"", /* checkpoint (with quotes!) */
+ 128, /* constack */
+ &instack, /* in */
+ &addbuf[0], /* addp */
+ &argsbuf[0], /* args */
+ &addbuf[0], /* addbuf */
+ &catbuf[0], /* catbuf */
+ 0, /* hdrbuf */
+ &hidebuf[0], /* hidebuf */
+ &pathbuf[0], /* path */
+ &tmpbuf[0], /* tmpbuf */
+ &valbuf[0], /* valbuf */
+ &optflags[0], /* optflags */
+ '\n', /* lastout */
+
+ /* the rest are implicitly initialized */
+};
+
+char ppctype[UCHAR_MAX];
diff --git a/usr/src/lib/libpp/common/pperror.c b/usr/src/lib/libpp/common/pperror.c
new file mode 100644
index 0000000000..46f7442ec7
--- /dev/null
+++ b/usr/src/lib/libpp/common/pperror.c
@@ -0,0 +1,38 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor error handler
+ */
+
+#include "pplib.h"
+
+void
+pperror(int level, ...)
+{
+ va_list ap;
+
+ va_start(ap, level);
+ errorv(pp.pass, level, ap);
+ va_end(ap);
+}
diff --git a/usr/src/lib/libpp/common/ppexpr.c b/usr/src/lib/libpp/common/ppexpr.c
new file mode 100644
index 0000000000..5fd93afde5
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppexpr.c
@@ -0,0 +1,697 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor expression evaluation support
+ */
+
+#include "pplib.h"
+
+#include <regex.h>
+
+#define lex(c) ((((c)=peektoken)>=0?(peektoken=(-1)):((c)=pplex())),(c))
+#define unlex(c) (peektoken=(c))
+
+static int peektoken; /* expression lookahead token */
+static char* errmsg; /* subexpr() error message */
+
+/*
+ * exists predicate evaluation
+ */
+
+static int
+exists(int op, char* pred, register char* args)
+{
+ register int c;
+ register int type;
+ char* pptoken;
+ long state;
+ char file[MAXTOKEN + 1];
+
+ state = (pp.state & ~DISABLE);
+ PUSH_STRING(args);
+ pptoken = pp.token;
+ pp.token = file;
+ pp.state |= HEADER|PASSEOF;
+ type = pplex();
+ pp.state &= ~HEADER;
+ pp.token = pptoken;
+ switch (type)
+ {
+ case T_STRING:
+ case T_HEADER:
+ break;
+ default:
+ error(1, "%s: \"...\" or <...> argument expected", pred);
+ c = 0;
+ goto done;
+ }
+ if (op == X_EXISTS)
+ {
+ if ((c = pplex()) == ',')
+ {
+ while ((c = pplex()) == T_STRING)
+ {
+ if (pathaccess(pp.path, pp.token, file, NiL, 0))
+ {
+ pathcanon(pp.path, 0);
+ message((-2, "%s: %s found", pred, pp.path));
+ c = 1;
+ goto done;
+ }
+ if ((c = pplex()) != ',') break;
+ }
+ if (c) error(1, "%s: \"...\" arguments expected", pred);
+ strcpy(pp.path, file);
+ message((-2, "%s: %s not found", pred, file));
+ c = 0;
+ }
+ else c = ppsearch(file, type, SEARCH_EXISTS) >= 0;
+ }
+ else
+ {
+ register struct ppfile* fp;
+
+ fp = ppsetfile(file);
+ c = fp->flags || fp->guard == INC_IGNORE;
+ }
+ done:
+ while (pplex());
+ pp.state = state;
+ return c;
+}
+
+/*
+ * strcmp/match predicate evaluation
+ */
+
+static int
+compare(char* pred, char* args, int match)
+{
+ register int c;
+ char* pptoken;
+ long state;
+ regex_t re;
+ char tmp[MAXTOKEN + 1];
+
+ state = (pp.state & ~DISABLE);
+ PUSH_STRING(args);
+ pp.state |= PASSEOF;
+ pptoken = pp.token;
+ pp.token = tmp;
+ if (!pplex())
+ goto bad;
+ pp.token = pptoken;
+ if (pplex() != ',' || !pplex())
+ goto bad;
+ if (!match)
+ c = strcmp(tmp, pp.token);
+ else if ((c = regcomp(&re, pp.token, REG_AUGMENTED|REG_LENIENT|REG_NULL)) || (c = regexec(&re, tmp, NiL, 0, 0)) && c != REG_NOMATCH)
+ regfatal(&re, 3, c);
+ else
+ {
+ c = !c;
+ regfree(&re);
+ }
+ if ((pp.state & PASSEOF) && pplex())
+ goto bad;
+ pp.state = state;
+ return c;
+ bad:
+ pp.token = pptoken;
+ error(2, "%s: 2 arguments expected", pred);
+ while (pplex());
+ pp.state = state;
+ return 0;
+}
+
+/*
+ * #if predicate parse and evaluation
+ */
+
+static int
+predicate(int warn)
+{
+ register char* args;
+ register struct pplist* p;
+ register struct ppsymbol* sym;
+ register int type;
+ int index;
+
+ static char pred[MAXID + 1];
+
+ /*
+ * first gather the args
+ */
+
+ index = (int)hashref(pp.strtab, pp.token);
+ if (warn && peekchr() != '(') switch (index)
+ {
+ case X_DEFINED:
+ case X_EXISTS:
+ case X_INCLUDED:
+ case X_MATCH:
+ case X_NOTICED:
+ case X_OPTION:
+ case X_SIZEOF:
+ case X_STRCMP:
+ break;
+ default:
+ if (pp.macref) pprefmac(pp.token, REF_IF);
+ return 0;
+ }
+ strcpy(pred, pp.token);
+ pp.state |= DISABLE;
+ type = pppredargs();
+ pp.state &= ~DISABLE;
+ switch (type)
+ {
+ case T_ID:
+ case T_STRING:
+ break;
+ default:
+ unlex(type);
+ /*FALLTHROUGH*/
+ case 0:
+ if (index && !(pp.state & STRICT))
+ error(1, "%s: predicate argument expected", pred);
+ if (pp.macref) pprefmac(pred, REF_IF);
+ return 0;
+ }
+ args = pp.args;
+
+ /*
+ * now evaluate
+ */
+
+ debug((-6, "pred=%s args=%s", pred, args));
+ if ((pp.state & STRICT) && !(pp.mode & HOSTED)) switch (index)
+ {
+ case X_DEFINED:
+ case X_SIZEOF:
+ break;
+ default:
+ error(1, "%s(%s): non-standard predicate test", pred, args);
+ return 0;
+ }
+ switch (index)
+ {
+ case X_DEFINED:
+ if (type != T_ID) error(1, "%s: identifier argument expected", pred);
+ else if ((sym = pprefmac(args, REF_IF)) && sym->macro) return 1;
+ else if (args[0] == '_' && args[1] == '_' && !strncmp(args, "__STDPP__", 9))
+ {
+ if (pp.hosted == 1 && pp.in->prev->type == IN_FILE)
+ {
+ pp.mode |= HOSTED;
+ pp.flags |= PP_hosted;
+ }
+ return *(args + 9) ? (int)hashref(pp.strtab, args + 9) : 1;
+ }
+ break;
+ case X_EXISTS:
+ case X_INCLUDED:
+ return exists(index, pred, args);
+ case X_MATCH:
+ case X_STRCMP:
+ return compare(pred, args, index == X_MATCH);
+ case X_NOTICED:
+ if (type != T_ID) error(1, "%s: identifier argument expected", pred);
+ else if (((sym = pprefmac(args, REF_IF)) || (sym = ppsymref(pp.symtab, args))) && (sym->flags & SYM_NOTICED)) return 1;
+ break;
+ case X_OPTION:
+ return ppoption(args);
+ case X_SIZEOF:
+ error(2, "%s invalid in #%s expressions", pred, dirname(IF));
+ break;
+ default:
+ if (warn && !(pp.mode & HOSTED) && (sym = ppsymref(pp.symtab, pred)) && (sym->flags & SYM_PREDICATE))
+ error(1, "use #%s(%s) to disambiguate", pred, args);
+ if (p = (struct pplist*)hashget(pp.prdtab, pred))
+ {
+ if (!*args) return 1;
+ while (p)
+ {
+ if (streq(p->value, args)) return 1;
+ p = p->next;
+ }
+ }
+ break;
+ }
+ return 0;
+}
+
+/*
+ * evaluate a long integer subexpression with precedence
+ * taken from the library routine streval()
+ * may be called recursively
+ *
+ * NOTE: all operands are evaluated as both the parse
+ * and evaluation are done on the fly
+ */
+
+static long
+subexpr(register int precedence, int* pun)
+{
+ register int c;
+ register long n;
+ register long x;
+ register int operand = 1;
+ int un = 0;
+ int xn;
+
+ switch (lex(c))
+ {
+ case 0:
+ case '\n':
+ unlex(c);
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected";
+ return 0;
+ case '-':
+ n = -subexpr(13, &un);
+ break;
+ case '+':
+ n = subexpr(13, &un);
+ break;
+ case '!':
+ n = !subexpr(13, &un);
+ break;
+ case '~':
+ n = ~subexpr(13, &un);
+ break;
+ default:
+ unlex(c);
+ n = 0;
+ operand = 0;
+ break;
+ }
+ un <<= 1;
+ for (;;)
+ {
+ switch (lex(c))
+ {
+ case 0:
+ case '\n':
+ goto done;
+ case ')':
+ if (!precedence)
+ {
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s";
+ return 0;
+ }
+ goto done;
+ case '(':
+ n = subexpr(1, &un);
+ if (lex(c) != ')')
+ {
+ unlex(c);
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected";
+ return 0;
+ }
+ gotoperand:
+ if (operand)
+ {
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected";
+ return 0;
+ }
+ operand = 1;
+ un <<= 1;
+ continue;
+ case '?':
+ if (precedence > 1) goto done;
+ un = 0;
+ if (lex(c) == ':')
+ {
+ if (!n) n = subexpr(2, &un);
+ else
+ {
+ x = pp.mode;
+ pp.mode |= INACTIVE;
+ subexpr(2, &xn);
+ pp.mode = x;
+ }
+ }
+ else
+ {
+ unlex(c);
+ x = subexpr(2, &xn);
+ if (lex(c) != ':')
+ {
+ unlex(c);
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator";
+ return 0;
+ }
+ if (n)
+ {
+ n = x;
+ un = xn;
+ subexpr(2, &xn);
+ }
+ else n = subexpr(2, &un);
+ }
+ break;
+ case ':':
+ goto done;
+ case T_ANDAND:
+ case T_OROR:
+ xn = (c == T_ANDAND) ? 4 : 3;
+ if (precedence >= xn) goto done;
+ if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0;
+ else
+ {
+ x = pp.mode;
+ pp.mode |= INACTIVE;
+ subexpr(xn, &un);
+ pp.mode = x;
+ }
+ un = 0;
+ break;
+ case '|':
+ if (precedence > 4) goto done;
+ n |= subexpr(5, &un);
+ break;
+ case '^':
+ if (precedence > 5) goto done;
+ n ^= subexpr(6, &un);
+ break;
+ case '&':
+ if (precedence > 6) goto done;
+ n &= subexpr(7, &un);
+ break;
+ case T_EQ:
+ case T_NE:
+ if (precedence > 7) goto done;
+ n = (n == subexpr(8, &un)) == (c == T_EQ);
+ un = 0;
+ break;
+ case '<':
+ case T_LE:
+ case T_GE:
+ case '>':
+ if (precedence > 8) goto done;
+ x = subexpr(9, &un);
+ switch (c)
+ {
+ case '<':
+ switch (un)
+ {
+ case 01:
+ n = n < (unsigned long)x;
+ break;
+ case 02:
+ n = (unsigned long)n < x;
+ break;
+ case 03:
+ n = (unsigned long)n < (unsigned long)x;
+ break;
+ default:
+ n = n < x;
+ break;
+ }
+ break;
+ case T_LE:
+ switch (un)
+ {
+ case 01:
+ n = n <= (unsigned long)x;
+ break;
+ case 02:
+ n = (unsigned long)n <= x;
+ break;
+ case 03:
+ n = (unsigned long)n <= (unsigned long)x;
+ break;
+ default:
+ n = n <= x;
+ break;
+ }
+ break;
+ case T_GE:
+ switch (un)
+ {
+ case 01:
+ n = n >= (unsigned long)x;
+ break;
+ case 02:
+ n = (unsigned long)n >= x;
+ break;
+ case 03:
+ n = (unsigned long)n >= (unsigned long)x;
+ break;
+ default:
+ n = n >= x;
+ break;
+ }
+ break;
+ case '>':
+ switch (un)
+ {
+ case 01:
+ n = n > (unsigned long)x;
+ break;
+ case 02:
+ n = (unsigned long)n > x;
+ break;
+ case 03:
+ n = (unsigned long)n > (unsigned long)x;
+ break;
+ default:
+ n = n > x;
+ break;
+ }
+ break;
+ }
+ un = 0;
+ break;
+ case T_LSHIFT:
+ case T_RSHIFT:
+ if (precedence > 9) goto done;
+ x = subexpr(10, &un);
+ if (c == T_LSHIFT) n <<= x;
+ else n >>= x;
+ un >>= 1;
+ break;
+ case '+':
+ case '-':
+ if (precedence > 10) goto done;
+ x = subexpr(11, &un);
+ if (c == '+') n += x;
+ else n -= x;
+ break;
+ case '*':
+ case '/':
+ case '%':
+ if (precedence > 11) goto done;
+ x = subexpr(12, &un);
+ if (c == '*') n *= x;
+ else if (x == 0)
+ {
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero";
+ return 0;
+ }
+ else if (c == '/') n /= x;
+ else n %= x;
+ break;
+ case '#':
+ pp.state |= DISABLE;
+ c = pplex();
+ pp.state &= ~DISABLE;
+ if (c != T_ID)
+ {
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier";
+ return 0;
+ }
+ n = predicate(0);
+ goto gotoperand;
+ case T_ID:
+ n = predicate(1);
+ goto gotoperand;
+ case T_CHARCONST:
+ c = *(pp.toknxt - 1);
+ *(pp.toknxt - 1) = 0;
+ n = chrtoi(pp.token + 1);
+ *(pp.toknxt - 1) = c;
+ if (n & ~((1<<CHAR_BIT)-1))
+ {
+ if (!(pp.mode & HOSTED))
+ error(1, "'%s': multi-character character constants are not portable", pp.token);
+ }
+#if CHAR_MIN < 0
+ else n = (char)n;
+#endif
+ goto gotoperand;
+ case T_DECIMAL_U:
+ case T_DECIMAL_UL:
+ case T_OCTAL_U:
+ case T_OCTAL_UL:
+ case T_HEXADECIMAL_U:
+ case T_HEXADECIMAL_UL:
+ un |= 01;
+ /*FALLTHROUGH*/
+ case T_DECIMAL:
+ case T_DECIMAL_L:
+ case T_OCTAL:
+ case T_OCTAL_L:
+ case T_HEXADECIMAL:
+ case T_HEXADECIMAL_L:
+ n = strtoul(pp.token, NiL, 0);
+ if ((unsigned long)n > LONG_MAX) un |= 01;
+ goto gotoperand;
+ case T_WCHARCONST:
+ n = chrtoi(pp.token);
+ goto gotoperand;
+ default:
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token";
+ return 0;
+ }
+ if (errmsg) return 0;
+ if (!operand) goto nooperand;
+ }
+ done:
+ unlex(c);
+ if (!operand)
+ {
+ nooperand:
+ if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected";
+ return 0;
+ }
+ if (un) *pun |= 01;
+ return n;
+}
+
+/*
+ * preprocessor expression evaluator using modified streval(3)
+ * *pun!=0 if result is unsigned
+ */
+
+long
+ppexpr(int* pun)
+{
+ long n;
+ int opeektoken;
+ long ppstate;
+
+ ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP));
+ pp.state &= ~(DISABLE|STRIP);
+ pp.state |= CONDITIONAL|NOSPACE;
+ opeektoken = peektoken;
+ peektoken = -1;
+ *pun = 0;
+ n = subexpr(0, pun);
+ if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :";
+ if (errmsg)
+ {
+ error(2, "%s in expression", errmsg);
+ errmsg = 0;
+ n = 0;
+ }
+ peektoken = opeektoken;
+ pp.state &= ~(CONDITIONAL|NOSPACE);
+ pp.state |= ppstate;
+ if (*pun) debug((-4, "ppexpr() = %luU", n));
+ else debug((-4, "ppexpr() = %ld", n));
+ return n;
+}
+
+/*
+ * return non-zero if option s is set
+ */
+
+int
+ppoption(char* s)
+{
+ switch ((int)hashget(pp.strtab, s))
+ {
+ case X_ALLMULTIPLE:
+ return pp.mode & ALLMULTIPLE;
+ case X_BUILTIN:
+ return pp.mode & BUILTIN;
+ case X_CATLITERAL:
+ return pp.mode & CATLITERAL;
+ case X_COMPATIBILITY:
+ return pp.state & COMPATIBILITY;
+ case X_DEBUG:
+ return -error_info.trace;
+ case X_ELSEIF:
+ return pp.option & ELSEIF;
+ case X_FINAL:
+ return pp.option & FINAL;
+ case X_HOSTDIR:
+ return pp.mode & HOSTED;
+ case X_HOSTED:
+ return pp.flags & PP_hosted;
+ case X_INITIAL:
+ return pp.option & INITIAL;
+ case X_KEYARGS:
+ return pp.option & KEYARGS;
+ case X_LINEBASE:
+ return pp.flags & PP_linebase;
+ case X_LINEFILE:
+ return pp.flags & PP_linefile;
+ case X_LINETYPE:
+ return pp.flags & PP_linetype;
+ case X_PLUSCOMMENT:
+ return pp.option & PLUSCOMMENT;
+ case X_PLUSPLUS:
+ return pp.option & PLUSPLUS;
+ case X_PLUSSPLICE:
+ return pp.option & PLUSSPLICE;
+ case X_PRAGMAEXPAND:
+ return pp.option & PRAGMAEXPAND;
+ case X_PREDEFINED:
+ return pp.option & PREDEFINED;
+ case X_PREFIX:
+ return pp.option & PREFIX;
+ case X_PROTOTYPED:
+ return pp.option & PROTOTYPED;
+ case X_READONLY:
+ return pp.mode & READONLY;
+ case X_REGUARD:
+ return pp.option & REGUARD;
+ case X_SPACEOUT:
+ return pp.state & SPACEOUT;
+ case X_SPLICECAT:
+ return pp.option & SPLICECAT;
+ case X_SPLICESPACE:
+ return pp.option & SPLICESPACE;
+ case X_STRICT:
+ return pp.state & STRICT;
+ case X_STRINGSPAN:
+ return pp.option & STRINGSPAN;
+ case X_STRINGSPLIT:
+ return pp.option & STRINGSPLIT;
+ case X_TEST:
+ return pp.test;
+ case X_TEXT:
+ return !(pp.state & NOTEXT);
+ case X_TRANSITION:
+ return pp.state & TRANSITION;
+ case X_TRUNCATE:
+ return pp.truncate;
+ case X_WARN:
+ return pp.state & WARN;
+ default:
+ if (pp.state & WARN) error(1, "%s: unknown option name", s);
+ return 0;
+ }
+}
diff --git a/usr/src/lib/libpp/common/ppfsm.c b/usr/src/lib/libpp/common/ppfsm.c
new file mode 100644
index 0000000000..5cef65db2a
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppfsm.c
@@ -0,0 +1,946 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor and proto lexical analyzer fsm
+ * define PROTOMAIN for standalone proto
+ */
+
+#include "pplib.h"
+#include "ppfsm.h"
+
+/*
+ * lexical FSM encoding
+ * derived from a standalone ansi cpp by Dennis Ritchie
+ * modified for libpp by Glenn Fowler
+ *
+ * fsm[] is initialized from fsminit[]. The encoding is blown out into
+ * fsm[] for time efficiency. When in state state, and one of the
+ * characters in ch arrives, enter nextstate. States >= TERMINAL are
+ * either final, or at least require special action. In fsminit[] there
+ * is a line for each <state,charset,nextstate>. Early entries are
+ * overwritten by later ones. C_XXX is the universal set and should
+ * always be first. Some of the fsminit[] entries are templates for
+ * groups of states. The OP entries trigger the state copies. States
+ * above TERMINAL are represented in fsm[] as negative values. S_TOK and
+ * S_TOKB encode the resulting token type in the upper bits. These actions
+ * differ in that S_TOKB has a lookahead char.
+ *
+ * fsm[] has three start states:
+ *
+ * PROTO proto (ANSI -> K&R,C++,ANSI)
+ * QUICK standalone ppcpp()
+ * TOKEN tokenizing pplex()
+ *
+ * If the next state remains the same then the fsm[] transition value is 0.
+ * MAX+1 is a power of 2 so that fsm[state][EOF==MAX+1] actually accesses
+ * fsm[state+1][0] which is ~S_EOB for all states. This preserves the
+ * power of 2 fsm[] row size for efficient array indexing. Thanks to
+ * D. G. Korn for the last two observations. The pseudo non-terminal state
+ * fsm[TERMINAL][state+1] is used to differentiate EOB from EOF.
+ *
+ * The bit layout is:
+ *
+ * TERM arg SPLICE next
+ * 15 14-8 7 6-0
+ */
+
+/*
+ * NOTE: these must be `control' characters for all native codesets
+ * currently ok for {ascii,ebcdic1,ebcdic2,ebcdic3}
+ */
+
+#define C_DEC 001
+#define C_EOF 002
+#define C_HEX 003
+#define C_LET 021
+#define C_OCT 022
+#define C_XXX 023
+
+#define OP (-1)
+#define END 0
+#define COPY 1
+
+#define copy(t,f) (memcpy(&fsm[t][1],&fsm[f][1],(MAX+1)*sizeof(short)),fsm[TERMINAL][(t)+1]=fsm[TERMINAL][(f)+1])
+
+struct fsminit /* fsm initialization row */
+{
+ int state; /* if in this state */
+ unsigned char ch[4]; /* and see one of these */
+ int nextstate; /* enter this state if <TERMINAL*/
+};
+
+static struct fsminit fsminit[] =
+{
+ /* proto start state */
+ { PROTO, { C_XXX }, S_CHR, },
+ { PROTO, { C_EOF }, S_EOF, },
+ { PROTO, { C_DEC }, BAD1, },
+ { PROTO, { '.' }, DOT, },
+ { PROTO, { C_LET }, NID, },
+ { PROTO, { 'L' }, LIT, },
+ { PROTO, { 'd', 'e', 'f', 'i' }, RES1, },
+ { PROTO, { 'r', 's', 't', 'v' }, RES1, },
+ { PROTO, { 'w', 'N' }, RES1, },
+ { PROTO, { '"', '\'' }, S_LITBEG, },
+ { PROTO, { '/' }, COM1, },
+ { PROTO, { '\n' }, S_NL, },
+ { PROTO, { ' ','\t','\f','\v' }, WS1, },
+
+/* proto {do,else,extern,for,if,inline,return,static,typedef,va_start,void,while,NoN} */
+ { RES1, { C_XXX }, S_MACRO, },
+ { RES1, { C_LET, C_DEC }, NID, },
+ { RES1, { 'a' }, RES1a, },
+ { RES1, { 'e' }, RES1e, },
+ { RES1, { 'f' }, RES1f, },
+ { RES1, { 'h' }, RES1h, },
+ { RES1, { 'l' }, RES1l, },
+ { RES1, { 'n' }, RES1n, },
+ { RES1, { 'o' }, RES1o, },
+ { RES1, { 't' }, RES1t, },
+ { RES1, { 'x' }, RES1x, },
+ { RES1, { 'y' }, RES1y, },
+
+ /* proto reserved {va_start} */
+ { RES1a, { C_XXX }, S_RESERVED, },
+ { RES1a, { C_LET, C_DEC }, NID, },
+ { RES1a, { '_','s','t','a' }, RES1a, },
+ { RES1a, { 'r' }, RES1a, },
+
+ /* proto reserved {return} */
+ { RES1e, { C_XXX }, S_RESERVED, },
+ { RES1e, { C_LET, C_DEC }, NID, },
+ { RES1e, { 't','u','r','n' }, RES1e, },
+
+ /* proto reserved {if} */
+ { RES1f, { C_XXX }, S_RESERVED, },
+ { RES1f, { C_LET, C_DEC }, NID, },
+
+ /* proto reserved {while} */
+ { RES1h, { C_XXX }, S_RESERVED, },
+ { RES1h, { C_LET, C_DEC }, NID, },
+ { RES1h, { 'i','l','e' }, RES1h, },
+
+ /* proto reserved {else} */
+ { RES1l, { C_XXX }, S_RESERVED, },
+ { RES1l, { C_LET, C_DEC }, NID, },
+ { RES1l, { 's','e' }, RES1l, },
+
+ /* proto reserved {inline} */
+ { RES1n, { C_XXX }, S_RESERVED, },
+ { RES1n, { C_LET, C_DEC }, NID, },
+ { RES1n, { 'l','i','n','e' }, RES1n, },
+
+ /* proto reserved {do,for,void} */
+ { RES1o, { C_XXX }, S_RESERVED, },
+ { RES1o, { C_LET, C_DEC }, NID, },
+ { RES1o, { 'r','i','d','N' }, RES1o, },
+
+ /* proto reserved {static} */
+ { RES1t, { C_XXX }, S_RESERVED, },
+ { RES1t, { C_LET, C_DEC }, NID, },
+ { RES1t, { 'a','t','i','c' }, RES1t, },
+
+ /* proto reserved {extern} */
+ { RES1x, { C_XXX }, S_RESERVED, },
+ { RES1x, { C_LET, C_DEC }, NID, },
+ { RES1x, { 't','e','r','n' }, RES1x, },
+
+ /* proto reserved {typedef} */
+ { RES1y, { C_XXX }, S_RESERVED, },
+ { RES1y, { C_LET, C_DEC }, NID, },
+ { RES1y, { 'p','e','d','f' }, RES1y, },
+
+ /* saw /, perhaps start of comment */
+ { COM1, { C_XXX }, S_CHRB, },
+ { COM1, { '*' }, COM2, },
+#if PROTOMAIN
+ { COM1, { '/' }, COM5, },
+#endif
+
+ /* saw / *, start of comment */
+ { COM2, { C_XXX }, COM2, },
+ { COM2, { '\n', C_EOF }, S_COMMENT, },
+ { COM2, { '/' }, COM4, },
+ { COM2, { '*' }, COM3, },
+ { COM2, { '#', ';', ')' }, QUAL(COM2), },
+
+ /* saw the * possibly ending a comment */
+ { COM3, { C_XXX }, COM2, },
+ { COM3, { '\n', C_EOF }, S_COMMENT, },
+ { COM3, { '#', ';', ')' }, QUAL(COM2), },
+ { COM3, { '*' }, COM3, },
+ { COM3, { '/' }, S_COMMENT, },
+
+ /* saw / in / * comment, possible malformed nest */
+ { COM4, { C_XXX }, COM2, },
+ { COM4, { '*', '\n', C_EOF }, S_COMMENT, },
+ { COM4, { '/' }, COM4, },
+
+ /* saw / /, start of comment */
+ { COM5, { C_XXX }, COM5, },
+ { COM5, { '\n', C_EOF }, S_COMMENT, },
+ { COM5, { '/' }, COM6, },
+ { COM5, { '*' }, COM7, },
+
+ /* saw / in / / comment, possible malformed nest */
+ { COM6, { C_XXX }, COM5, },
+ { COM6, { '*', '\n', C_EOF }, S_COMMENT, },
+ { COM6, { '/' }, COM6, },
+
+ /* saw * in / /, possible malformed nest */
+ { COM7, { C_XXX }, COM5, },
+ { COM7, { '\n', C_EOF }, S_COMMENT, },
+ { COM7, { '*' }, COM7, },
+ { COM7, { '/' }, S_COMMENT, },
+
+ /* normal identifier -- always a macro candidate */
+ { NID, { C_XXX }, S_MACRO, },
+ { NID, { C_LET, C_DEC }, NID, },
+
+ /* saw ., operator or dbl constant */
+ { DOT, { C_XXX }, S_CHRB, },
+ { DOT, { '.' }, DOT2, },
+ { DOT, { C_DEC }, BAD1, },
+
+ /* saw .., possible ... */
+ { DOT2, { C_XXX }, BACK(T_INVALID), },
+ { DOT2, { '.' }, KEEP(T_VARIADIC), },
+
+ /* saw L (possible start of normal wide literal) */
+ { LIT, { C_XXX }, S_MACRO, },
+ { LIT, { C_LET, C_DEC }, NID, },
+ { LIT, { '"', '\'' }, QUAL(LIT1), },
+
+ /* saw " or ' beginning literal */
+ { LIT1, { C_XXX }, LIT1, },
+ { LIT1, { '"', '\'' }, S_LITEND, },
+ { LIT1, { '\n', C_EOF }, S_LITEND, },
+ { LIT1, { '\\' }, LIT2, },
+
+ /* saw \ in literal */
+ { LIT2, { C_XXX }, S_LITESC, },
+ { LIT2, { '\n', C_EOF }, S_LITEND, },
+
+ /* eat malformed numeric constant */
+ { BAD1, { C_XXX }, BACK(T_INVALID), },
+ { BAD1, { C_LET, C_DEC, '.' }, BAD1, },
+ { BAD1, { 'e', 'E' }, BAD2, },
+
+ /* eat malformed numeric fraction|exponent */
+ { BAD2, { C_XXX }, BACK(T_INVALID), },
+ { BAD2, { C_LET, C_DEC, '.' }, BAD1, },
+ { BAD2, { '+', '-' }, BAD1, },
+
+ /* saw white space, eat it up */
+ { WS1, { C_XXX }, S_WS, },
+ { WS1, { ' ', '\t' }, WS1, },
+ { WS1, { '\f', '\v' }, S_VS, },
+
+#if !PROTOMAIN
+
+ /* quick template */
+ { QUICK, { C_XXX }, QTOK, },
+ { QUICK, { C_EOF, MARK }, S_CHRB, },
+ { QUICK, { C_LET, C_DEC }, QID, },
+ { QUICK, { 'L' }, LIT0, },
+ { QUICK, { '"', '\'' }, S_LITBEG, },
+ { QUICK, { '/' }, S_CHRB, },
+ { QUICK, { '*' }, QCOM, },
+ { QUICK, { '#' }, SHARP1, },
+ { QUICK, { '\n' }, S_NL, },
+ { QUICK, { '\f', '\v' }, S_VS, },
+
+ /* copy QUICK to QUICK+1 through MAC0+1 */
+ { OP, {QUICK,QUICK+1,MAC0+1}, COPY, },
+
+ /* quick start state */
+ { QUICK, { C_EOF }, S_EOF, },
+ { QUICK, { C_DEC }, QNUM, },
+ { QUICK, { MARK }, QTOK, },
+ { QUICK, { '/' }, COM1, },
+ { QUICK, { ' ', '\t' }, QUICK, },
+
+ /* grab non-macro tokens */
+ { QTOK, { C_DEC }, QNUM, },
+
+ /* grab numeric and invalid tokens */
+ { QNUM, { C_LET, C_DEC, '.' }, QNUM, },
+ { QNUM, { 'e', 'E' }, QEXP, },
+
+ /* grab exponent token */
+ { QEXP, { C_LET, C_DEC, '.' }, QNUM, },
+ { QEXP, { '+', '-' }, QNUM, },
+
+ /* saw *, grab possible bad comment terminator */
+ { QCOM, { C_DEC }, QNUM, },
+ { QCOM, { '/' }, S_COMMENT, },
+
+ /* saw L (possible start of wide string or first macro char) */
+ { MAC0, { 'L' }, QID, },
+ { MAC0, { '"', '\'' }, QUAL(LIT1), },
+
+ /* macro candidate template */
+ { MAC0+1, { 'L' }, QID, },
+
+ /* copy MAC0+1 to MAC0+2 through MACN */
+ { OP, {MAC0+1,MAC0+2,MACN}, COPY },
+
+ /* saw L (possible start of wide string or macro L) */
+ { HIT0, { C_XXX }, S_MACRO, },
+ { HIT0, { C_LET, C_DEC }, QID, },
+ { HIT0, { '"', '\'' }, QUAL(LIT1), },
+
+ /* macro hit template */
+ { HIT0+1, { C_XXX }, S_MACRO, },
+ { HIT0+1, { C_LET, C_DEC }, QID, },
+
+ /* copy HIT0+1 to HIT0+2 through HITN */
+ { OP, {HIT0+1,HIT0+2,HITN}, COPY },
+
+ /* saw L (possible start of wide literal) */
+ { LIT0, { C_XXX }, S_MACRO, },
+ { LIT0, { C_LET, C_DEC }, QID, },
+ { LIT0, { '"', '\'' }, QUAL(LIT1), },
+
+ /* (!PROTOMAIN COM1) saw /, perhaps start of comment or /= */
+ { COM1, { '=' }, KEEP(T_DIVEQ), },
+
+ /* normal start state */
+ { TOKEN, { C_XXX }, S_HUH, },
+ { TOKEN, { C_EOF }, S_EOF, },
+ { TOKEN, { C_DEC }, DEC1, },
+ { TOKEN, { '0' }, OCT1, },
+ { TOKEN, { '.' }, DOT1, },
+ { TOKEN, { C_LET }, NID, },
+ { TOKEN, { 'L' }, LIT, },
+ { TOKEN, { '"', '\'', '<' }, S_LITBEG, },
+ { TOKEN, { '/' }, COM1, },
+ { TOKEN, { '\n' }, S_NL, },
+ { TOKEN, { ' ', '\t' }, WS1, },
+ { TOKEN, { '\f', '\v' }, S_VS, },
+ { TOKEN, { '#' }, SHARP1, },
+ { TOKEN, { ':' }, COLON1, },
+ { TOKEN, { '%' }, PCT1, },
+ { TOKEN, { '&' }, AND1, },
+ { TOKEN, { '*' }, STAR1, },
+ { TOKEN, { '+' }, PLUS1, },
+ { TOKEN, { '-' }, MINUS1, },
+ { TOKEN, { '=' }, EQ1, },
+ { TOKEN, { '!' }, NOT1, },
+ { TOKEN, { '>' }, GT1, },
+ { TOKEN, { '^' }, CIRC1, },
+ { TOKEN, { '|' }, OR1, },
+ { TOKEN, { '(', ')', '[', ']' }, S_CHR, },
+ { TOKEN, { '{', '}', ',', ';' }, S_CHR, },
+ { TOKEN, { '~', '?' }, S_CHR, },
+
+ /* saw 0, possible oct|hex|dec|dbl constant */
+ { OCT1, { C_XXX }, BACK(T_DECIMAL), },
+ { OCT1, { C_LET, C_DEC }, BAD1, },
+ { OCT1, { C_OCT }, OCT2, },
+ { OCT1, { 'e', 'E' }, DBL2, },
+ { OCT1, { 'l', 'L', 'u', 'U' }, QUAL(DEC2), },
+ { OCT1, { 'x', 'X' }, HEX1, },
+ { OCT1, { '.' }, DBL1, },
+
+ /* saw 0<oct>, oct constant */
+ { OCT2, { C_XXX }, BACK(T_OCTAL), },
+ { OCT2, { C_LET, C_DEC }, BAD1, },
+ { OCT2, { C_OCT }, OCT2, },
+ { OCT2, { 'e', 'E' }, DBL2, },
+ { OCT2, { 'l', 'L', 'u', 'U' }, QUAL(OCT3), },
+ { OCT2, { '.' }, DBL1, },
+
+ /* oct constant qualifier */
+ { OCT3, { C_XXX }, BACK(T_OCTAL), },
+ { OCT3, { C_LET, C_DEC, '.' }, BAD1, },
+ { OCT3, { 'l', 'L', 'u', 'U' }, QUAL(OCT3), },
+
+ /* saw 0 [xX], hex constant */
+ { HEX1, { C_XXX }, BACK(T_HEXADECIMAL), },
+ { HEX1, { C_LET }, BAD1, },
+ { HEX1, { C_HEX }, HEX1, },
+ { HEX1, { 'e', 'E' }, HEX3, },
+ { HEX1, { 'l', 'L', 'u', 'U' }, QUAL(HEX2), },
+ { HEX1, { '.' }, HEX4, },
+ { HEX1, { 'p', 'P' }, HEX5, },
+
+ /* hex constant qualifier */
+ { HEX2, { C_XXX }, BACK(T_HEXADECIMAL), },
+ { HEX2, { C_LET, C_DEC, '.' }, BAD1, },
+ { HEX2, { 'l', 'L', 'u', 'U' }, QUAL(HEX2), },
+
+ /* hex [eE][-+] botch */
+ { HEX3, { C_XXX }, BACK(T_HEXADECIMAL), },
+ { HEX3, { C_LET, '.', '-', '+'},BAD1, },
+ { HEX3, { C_HEX }, HEX1, },
+ { HEX3, { 'e', 'E' }, HEX3, },
+ { HEX3, { 'l', 'L', 'u', 'U' }, QUAL(HEX2), },
+
+ /* hex dbl fraction */
+ { HEX4, { C_XXX }, BACK(T_HEXDOUBLE), },
+ { HEX4, { C_LET, '.' }, BAD1, },
+ { HEX4, { C_HEX }, HEX4, },
+ { HEX4, { 'p', 'P' }, HEX5, },
+ { HEX4, { 'f', 'F', 'l', 'L' }, QUAL(HEX8), },
+
+ /* optional hex dbl exponent sign */
+ { HEX5, { C_XXX }, BACK(T_INVALID), },
+ { HEX5, { C_LET, '.' }, BAD1, },
+ { HEX5, { '+', '-' }, HEX6, },
+ { HEX5, { C_DEC }, HEX7, },
+
+ /* mandatory hex dbl exponent first digit */
+ { HEX6, { C_XXX }, BACK(T_INVALID), },
+ { HEX6, { C_LET, '.' }, BAD1, },
+ { HEX6, { C_DEC }, HEX7, },
+
+ /* hex dbl exponent digits */
+ { HEX7, { C_XXX }, BACK(T_HEXDOUBLE), },
+ { HEX7, { C_LET, '.' }, BAD1, },
+ { HEX7, { C_DEC }, HEX7, },
+ { HEX7, { 'f', 'F', 'l', 'L' }, QUAL(HEX8), },
+
+ /* hex dbl constant qualifier */
+ { HEX8, { C_XXX }, BACK(T_HEXDOUBLE), },
+ { HEX8, { C_LET, '.' }, BAD1, },
+ { HEX8, { 'f', 'F', 'l', 'L' }, QUAL(HEX8), },
+
+ /* saw <dec>, dec constant */
+ { DEC1, { C_XXX }, BACK(T_DECIMAL), },
+ { DEC1, { C_LET }, BAD1, },
+ { DEC1, { C_DEC }, DEC1, },
+ { DEC1, { 'e', 'E' }, DBL2, },
+ { DEC1, { 'l', 'L', 'u', 'U' }, QUAL(DEC2), },
+ { DEC1, { '.' }, DBL1, },
+
+ /* dec constant qualifier */
+ { DEC2, { C_XXX }, BACK(T_DECIMAL), },
+ { DEC2, { C_LET, C_DEC }, BAD1, },
+ { DEC2, { 'l', 'L', 'u', 'U' }, QUAL(DEC2), },
+
+ /* saw ., operator or dbl constant */
+ { DOT1, { C_XXX }, S_CHRB, },
+ { DOT1, { '.' }, DOT2, },
+ { DOT1, { C_DEC }, DBL1, },
+
+ /* dbl fraction */
+ { DBL1, { C_XXX }, BACK(T_DOUBLE), },
+ { DBL1, { C_LET, '.' }, BAD1, },
+ { DBL1, { C_DEC }, DBL1, },
+ { DBL1, { 'e', 'E' }, DBL2, },
+ { DBL1, { 'f', 'F', 'l', 'L' }, QUAL(DBL5), },
+
+ /* optional dbl exponent sign */
+ { DBL2, { C_XXX }, BACK(T_INVALID), },
+ { DBL2, { C_LET, '.' }, BAD1, },
+ { DBL2, { '+', '-' }, DBL3, },
+ { DBL2, { C_DEC }, DBL4, },
+
+ /* mandatory dbl exponent first digit */
+ { DBL3, { C_XXX }, BACK(T_INVALID), },
+ { DBL3, { C_LET, '.' }, BAD1, },
+ { DBL3, { C_DEC }, DBL4, },
+
+ /* dbl exponent digits */
+ { DBL4, { C_XXX }, BACK(T_DOUBLE), },
+ { DBL4, { C_LET, '.' }, BAD1, },
+ { DBL4, { C_DEC }, DBL4, },
+ { DBL4, { 'f', 'F', 'l', 'L' }, QUAL(DBL5), },
+
+ /* dbl constant qualifier */
+ { DBL5, { C_XXX }, BACK(T_DOUBLE), },
+ { DBL5, { C_LET, '.' }, BAD1, },
+ { DBL5, { 'f', 'F', 'l', 'L' }, QUAL(DBL5), },
+
+ /* saw < starting include header */
+ { HDR1, { C_XXX }, HDR1, },
+ { HDR1, { '>', '\n', C_EOF }, S_LITEND, },
+
+ /* saw <binop><space> expecting = */
+ { BIN1, { C_XXX }, S_HUH, },
+ { BIN1, { ' ', '\t' }, BIN1, },
+
+ /* 2-char ops */
+
+ { SHARP1, { C_XXX }, S_SHARP, },
+
+ { PCT1, { C_XXX }, S_CHRB, },
+ { PCT1, { '=' }, KEEP(T_MODEQ), },
+
+ { AND1, { C_XXX }, S_CHRB, },
+ { AND1, { '=' }, KEEP(T_ANDEQ), },
+ { AND1, { '&' }, KEEP(T_ANDAND), },
+
+ { STAR1, { C_XXX }, S_CHRB, },
+ { STAR1, { '=' }, KEEP(T_MPYEQ), },
+ { STAR1, { '/' }, S_COMMENT, },
+
+ { PLUS1, { C_XXX }, S_CHRB, },
+ { PLUS1, { '=' }, KEEP(T_ADDEQ), },
+ { PLUS1, { '+' }, KEEP(T_ADDADD), },
+
+ { MINUS1, { C_XXX }, S_CHRB, },
+ { MINUS1, { '=' }, KEEP(T_SUBEQ), },
+ { MINUS1, { '-' }, KEEP(T_SUBSUB), },
+ { MINUS1, { '>' }, KEEP(T_PTRMEM), },
+
+ { COLON1, { C_XXX }, S_CHRB, },
+ { COLON1, { '=', '>' }, S_HUH, },
+
+ { LT1, { C_XXX }, S_CHRB, },
+ { LT1, { '=' }, KEEP(T_LE), },
+ { LT1, { '<' }, LSH1, },
+
+ { EQ1, { C_XXX }, S_CHRB, },
+ { EQ1, { '=' }, KEEP(T_EQ), },
+
+ { NOT1, { C_XXX }, S_CHRB, },
+ { NOT1, { '=' }, KEEP(T_NE), },
+
+ { GT1, { C_XXX }, S_CHRB, },
+ { GT1, { '=' }, KEEP(T_GE), },
+ { GT1, { '>' }, RSH1, },
+
+ { CIRC1, { C_XXX }, S_CHRB, },
+ { CIRC1, { '=' }, KEEP(T_XOREQ), },
+
+ { OR1, { C_XXX }, S_CHRB, },
+ { OR1, { '=' }, KEEP(T_OREQ), },
+ { OR1, { '|' }, KEEP(T_OROR), },
+
+ /* 3-char ops */
+
+ { ARROW1, { C_XXX }, BACK(T_PTRMEM), },
+ { ARROW1, { '*' }, KEEP(T_PTRMEMREF), },
+
+ { LSH1, { C_XXX }, BACK(T_LSHIFT), },
+ { LSH1, { '=' }, KEEP(T_LSHIFTEQ), },
+
+ { RSH1, { C_XXX }, BACK(T_RSHIFT), },
+ { RSH1, { '=' }, KEEP(T_RSHIFTEQ), },
+
+#endif
+
+ /* end */
+ { OP, { 0 }, END, }
+};
+
+short fsm[TERMINAL+1][MAX+1];
+
+char trigraph[MAX+1];
+
+#if PROTOMAIN
+static char spl[] = { '\\', '\r', 0 };
+static char aln[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_$@";
+#else
+static char spl[] = { MARK, '?', '\\', '\r', CC_sub, 0 };
+static char aln[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
+#endif
+static char* let = &aln[10];
+static char hex[] = "fedcbaFEDCBA9876543210";
+static char* dec = &hex[12];
+static char* oct = &hex[14];
+
+/*
+ * runtime FSM modifications
+ * ppfsm(FSM_INIT,0) must be called first
+ */
+
+void
+ppfsm(int op, register char* s)
+{
+ register int c;
+ register int n;
+ register int i;
+ register short* rp;
+ register struct fsminit* fp;
+#if !PROTOMAIN
+ char* t;
+ int x;
+#endif
+
+ switch (op)
+ {
+
+#if !PROTOMAIN
+
+ case FSM_IDADD:
+ while (c = *s++)
+ if (!ppisid(c))
+ {
+ if (fsm[TOKEN][c] == ~S_HUH)
+ {
+ setid(c);
+ for (i = 0; i < TERMINAL; i++)
+ fsm[i][c] = IDSTATE(fsm[i]['_']);
+ }
+ else error(2, "%c: cannot add to identifier set", c);
+ }
+ break;
+
+ case FSM_IDDEL:
+ while (c = *s++)
+ if (ppisid(c))
+ {
+ clrid(c);
+ for (i = 0; i < TERMINAL; i++)
+ fsm[i][c] = ~S_HUH;
+ }
+ break;
+
+#endif
+
+ case FSM_INIT:
+ for (fp = fsminit;; fp++)
+ {
+ if ((n = fp->nextstate) >= TERMINAL) n = ~n;
+ if (fp->state == OP)
+ {
+#if !PROTOMAIN
+ switch (n)
+ {
+ case COPY:
+ c = fp->ch[0];
+ n = fp->ch[2];
+ for (i = fp->ch[1]; i <= n; i++)
+ copy(i, c);
+ continue;
+ default:
+ break;
+ }
+#endif
+ break;
+ }
+ rp = fsm[fp->state];
+ for (i = 0; i < sizeof(fp->ch) && (c = fp->ch[i]); i++)
+ {
+ switch (c)
+ {
+ case C_XXX:
+ for (c = 0; c <= MAX; c++)
+ rp[c] = n;
+ /*FALLTHROUGH*/
+
+ case C_EOF:
+ fsm[TERMINAL][fp->state+1] = n < 0 ? ~n : n;
+ continue;
+
+ case C_LET:
+ s = let;
+ break;
+
+ case C_HEX:
+ s = hex;
+ break;
+
+ case C_DEC:
+ s = dec;
+ break;
+
+ case C_OCT:
+ s = oct;
+ break;
+
+ default:
+ rp[c] = n;
+ continue;
+ }
+ while (c = *s++)
+ rp[c] = n;
+ }
+ }
+
+ /*
+ * install splice special cases
+ * and same non-terminal transitions
+ */
+
+ for (i = 0; i < TERMINAL; i++)
+ {
+ rp = fsm[i];
+ s = spl;
+ while (c = *s++)
+ if (c != MARK || !INCOMMENT(rp))
+ {
+ if (rp[c] >= 0) rp[c] = ~rp[c];
+ rp[c] &= ~SPLICE;
+ }
+ rp[EOB] = ~S_EOB;
+ for (c = 0; c <= MAX; c++)
+ if (rp[c] == i)
+ rp[c] = 0;
+ }
+ fsm[TERMINAL][0] = ~S_EOB;
+
+#if !PROTOMAIN
+
+ /*
+ * default character types
+ */
+
+ s = let;
+ while (c = *s++)
+ setid(c);
+ s = dec;
+ while (c = *s++)
+ setdig(c);
+ s = spl;
+ do setsplice(c = *s++); while (c);
+
+ /*
+ * trigraph map
+ */
+
+ trigraph['='] = '#';
+ trigraph['('] = '[';
+ trigraph['/'] = '\\';
+ trigraph[')'] = ']';
+ trigraph['\''] = '^';
+ trigraph['<'] = '{';
+ trigraph['!'] = '|';
+ trigraph['>'] = '}';
+ trigraph['-'] = '~';
+#endif
+ break;
+
+#if !PROTOMAIN
+
+ case FSM_PLUSPLUS:
+ if (pp.option & PLUSPLUS)
+ {
+ fsm[COLON1][':'] = ~KEEP(T_SCOPE);
+ fsm[DOT1]['*'] = ~KEEP(T_DOTREF);
+ fsm[MINUS1]['>'] = ARROW1;
+ fsm[COM1]['/'] = COM5;
+ t = "%<:";
+ for (i = 0; i < TERMINAL; i++)
+ {
+ rp = fsm[i];
+ if (!INCOMMENT(rp) && !INQUOTE(rp))
+ {
+ s = t;
+ while (c = *s++)
+ {
+ if (rp[c] > 0) rp[c] = ~rp[c];
+ else if (!rp[c]) rp[c] = ~i;
+ rp[c] &= ~SPLICE;
+ }
+ }
+ }
+ s = t;
+ while (c = *s++) setsplice(c);
+ }
+ else
+ {
+ fsm[COLON1][':'] = ~S_CHRB;
+ fsm[DOT1]['*'] = ~S_CHRB;
+ fsm[MINUS1]['>'] = ~KEEP(T_PTRMEM);
+ fsm[COM1]['/'] = (pp.option & PLUSCOMMENT) ? COM5 : ~S_CHRB;
+ }
+ break;
+
+#if COMPATIBLE
+
+ case FSM_COMPATIBILITY:
+ if (pp.state & COMPATIBILITY)
+ {
+ fsm[HEX1]['e'] = HEX1;
+ fsm[HEX1]['E'] = HEX1;
+ fsm[QNUM]['e'] = QNUM;
+ fsm[QNUM]['E'] = QNUM;
+ fsm[QNUM]['u'] = ~QUAL(QNUM);
+ fsm[QNUM]['U'] = ~QUAL(QNUM);
+ }
+ else
+ {
+ fsm[HEX1]['e'] = HEX3;
+ fsm[HEX1]['E'] = HEX3;
+ fsm[QNUM]['e'] = QEXP;
+ fsm[QNUM]['E'] = QEXP;
+ fsm[QNUM]['u'] = QNUM;
+ fsm[QNUM]['U'] = QNUM;
+ }
+ break;
+
+#endif
+
+ case FSM_QUOTADD:
+ while (c = *s++)
+ if (fsm[TOKEN][c] == ~S_HUH)
+ for (i = 0; i < TERMINAL; i++)
+ fsm[i][c] = fsm[i]['"'];
+ else error(2, "%c: cannot add to quote set", c);
+ break;
+
+ case FSM_QUOTDEL:
+ while (c = *s++)
+ if (c != '"' && fsm[TOKEN][c] == fsm[TOKEN]['"'])
+ for (i = 0; i < TERMINAL; i++)
+ fsm[i][c] = fsm[i]['_'];
+ break;
+
+ case FSM_OPSPACE:
+ n = s ? BIN1 : ~S_CHRB;
+ fsm[COM1][' '] = fsm[COM1]['\t'] = n;
+ fsm[AND1][' '] = fsm[AND1]['\t'] = n;
+ fsm[STAR1][' '] = fsm[STAR1]['\t'] = n;
+ fsm[PCT1][' '] = fsm[PCT1]['\t'] = n;
+ fsm[PLUS1][' '] = fsm[PLUS1]['\t'] = n;
+ fsm[MINUS1][' '] = fsm[MINUS1]['\t'] = n;
+ fsm[CIRC1][' '] = fsm[CIRC1]['\t'] = n;
+ fsm[OR1][' '] = fsm[OR1]['\t'] = n;
+ fsm[LSH1][' '] = fsm[LSH1]['\t'] = s ? BIN1 : ~BACK(T_LSHIFT);
+ fsm[RSH1][' '] = fsm[RSH1]['\t'] = s ? BIN1 : ~BACK(T_RSHIFT);
+ break;
+
+ case FSM_MACRO:
+ if (pp.truncate && strlen(s) >= pp.truncate)
+ {
+ x = s[pp.truncate];
+ s[pp.truncate] = 0;
+ }
+ else x = -1;
+ i = MAC0 + ((c = *s++) != 'L');
+ if ((n = fsm[QUICK][c]) != (i + NMAC))
+ {
+ n = i;
+ if (!*s) n += NMAC;
+ }
+ if (fsm[QUICK][c] != n)
+ fsm[QUICK][c] = fsm[QCOM][c] = fsm[QTOK][c] = n;
+ if (c = *s++)
+ {
+ for (;;)
+ {
+ if ((i = n) < HIT0)
+ {
+ if (n < MACN) n++;
+ if (!*s)
+ {
+ n += NMAC;
+ break;
+ }
+ if (fsm[i][c] < HIT0)
+ fsm[i][c] = n;
+ if (fsm[i + NMAC][c] < HIT0)
+ fsm[i + NMAC][c] = n;
+ }
+ else
+ {
+ if (n < HITN) n++;
+ if (!*s) break;
+ if (fsm[i][c] < HIT0)
+ {
+ n -= NMAC;
+ fsm[i][c] = n;
+ }
+ }
+ c = *s++;
+ }
+ if (x >= 0)
+ {
+ *s = x;
+ for (n = CHAR_MIN; n <= CHAR_MAX; n++)
+ if (ppisidig(n))
+ fsm[HITN][n] = HITN;
+ n = HITN;
+ }
+ if (fsm[i][c] < n)
+ fsm[i][c] = n;
+ if (i < HIT0 && fsm[i + NMAC][c] < n)
+ fsm[i + NMAC][c] = n;
+ }
+ break;
+
+#endif
+
+ }
+}
+
+#if !PROTOMAIN
+
+/*
+ * file buffer refill
+ * c is current input char
+ */
+
+void
+refill(register int c)
+{
+ if (pp.in->flags & IN_eof)
+ {
+ pp.in->nextchr--;
+ c = 0;
+ }
+ else
+ {
+ *((pp.in->nextchr = pp.in->buffer + PPBAKSIZ) - 1) = c;
+ c =
+#if PROTOTYPE
+ (pp.in->flags & IN_prototype) ? pppread(pp.in->nextchr) :
+#endif
+ read(pp.in->fd, pp.in->nextchr, PPBUFSIZ);
+ }
+ if (c > 0)
+ {
+ if (pp.in->nextchr[c - 1] == '\n') pp.in->flags |= IN_newline;
+ else pp.in->flags &= ~IN_newline;
+#if PROTOTYPE
+ if (!(pp.in->flags & IN_prototype))
+#endif
+ if (c < PPBUFSIZ && (pp.in->flags & IN_regular))
+ {
+ pp.in->flags |= IN_eof;
+ close(pp.in->fd);
+ pp.in->fd = -1;
+ }
+ }
+ else
+ {
+ if (c < 0)
+ {
+ error(ERROR_SYSTEM|3, "read error");
+ c = 0;
+ }
+ else if ((pp.in->flags ^ pp.in->prev->flags) & IN_c)
+ {
+ static char ket[] = { 0, '}', '\n', 0 };
+
+ pp.in->flags ^= IN_c;
+ pp.in->nextchr = ket + 1;
+ c = 2;
+ }
+ pp.in->flags |= IN_eof;
+ }
+#if CHECKPOINT
+ pp.in->buflen = c;
+#endif
+ pp.in->nextchr[c] = 0;
+ debug((-7, "refill(\"%s\") = %d = \"%-.*s%s\"", error_info.file, c, (c > 32 ? 32 : c), pp.in->nextchr, c > 32 ? "..." : ""));
+ if (pp.test & 0x0080)
+ sfprintf(sfstderr, "===== refill(\"%s\") = %d =====\n%s\n===== eob(\"%s\") =====\n", error_info.file, c, pp.in->nextchr, error_info.file);
+}
+
+#endif
diff --git a/usr/src/lib/libpp/common/ppfsm.h b/usr/src/lib/libpp/common/ppfsm.h
new file mode 100644
index 0000000000..1aff931d2b
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppfsm.h
@@ -0,0 +1,278 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor lexical analyzer definitions
+ */
+
+#ifndef _PPFSM_H
+#define _PPFSM_H
+
+#define BITSTATE 16 /* bitsof(state) */
+#define BITNONTERM 7 /* bitsof(non-terminal-state) */
+#define BITTERM 7 /* bitsof(terminal-state) */
+#define NMAC 19 /* number of MAC states */
+
+#define SPLICE (1<<BITTERM)
+
+#define CODE(tok,act) ((((tok)-N_PP)<<(BITTERM+1))|(act))
+#define TERM(st) ((st)&((1<<(BITTERM+1))-1))
+#define NEXT(st) (((st)>>(BITTERM+1))&((1<<BITNONTERM)-1))
+#define QUAL(st) (((st)<<(BITTERM+1))|(S_QUAL))
+#define TYPE(st) (NEXT(st)+N_PP)
+
+#define BACK(tok) CODE(tok,S_TOKB)
+#define KEEP(tok) CODE(tok,S_TOK)
+
+#undef MAX
+#define MAX 255
+
+#undef EOB
+#define EOB 0
+#undef EOF
+#define EOF (MAX+1)
+
+/*
+ * FSM states
+ *
+ * NOTE: preserve the ranges
+ */
+
+#define INDEX(p) (((p)-fsm[0])/(MAX+1))
+
+#define IDSTATE(x) (((x)>=0&&INQMACRO(fsm[x]))?QID:(x))
+
+#define INCOMMENT(p) ((p)>=fsm[COM2]&&(p)<=fsm[COM7])
+#define INCOMMENTXX(p) ((p)>=fsm[COM5]&&(p)<=fsm[COM7])
+#define INQMACRO(p) ((p)>=fsm[MAC0]&&(p)<=fsm[LIT0])
+#define INTMACRO(p) ((p)>=fsm[NID]&&(p)<=fsm[LIT])
+#define INQUOTE(p) ((p)>=fsm[LIT1]&&(p)<=fsm[LIT2])
+#define INOPSPACE(p) ((p)==fsm[BIN1])
+#define INSPACE(p) ((p)==fsm[WS1])
+
+/*
+ * proto non-terminal states
+ */
+
+#define PROTO 0
+#define RES1 (PROTO+1)
+#define RES1a (PROTO+2)
+#define RES1e (PROTO+3)
+#define RES1f (PROTO+4)
+#define RES1h (PROTO+5)
+#define RES1l (PROTO+6)
+#define RES1n (PROTO+7)
+#define RES1o (PROTO+8)
+#define RES1t (PROTO+9)
+#define RES1x (PROTO+10)
+#define RES1y (PROTO+11)
+#define COM1 (PROTO+12)
+#define COM2 (PROTO+13)
+#define COM3 (PROTO+14)
+#define COM4 (PROTO+15)
+#define COM5 (PROTO+16)
+#define COM6 (PROTO+17)
+#define COM7 (PROTO+18)
+#define NID (PROTO+19)
+#define LIT (PROTO+20)
+#define LIT1 (PROTO+21)
+#define LIT2 (PROTO+22)
+#define BAD1 (PROTO+23)
+#define BAD2 (PROTO+24)
+#define DOT (PROTO+25)
+#define DOT2 (PROTO+26)
+#define WS1 (PROTO+27)
+
+#if PROTOMAIN
+
+#define TERMINAL (PROTO+28) /* PROTOMAIN */
+
+#else
+
+/*
+ * quick non-terminal states
+ */
+
+#define QUICK (PROTO+28)
+#define QTOK (QUICK+1)
+#define QNUM (QUICK+2)
+#define QEXP (QUICK+3)
+#define QCOM (QUICK+4)
+#define QID (QUICK+5)
+#define MAC0 (QUICK+6)
+#define MACN (MAC0+NMAC-1)
+#define HIT0 (MACN+1)
+#define HITN (HIT0+NMAC-1)
+#define LIT0 (HITN+1)
+#define SHARP1 (HITN+2)
+
+/*
+ * tokenize non-terminal states
+ */
+
+#define TOKEN (HITN+3)
+#define OCT1 (TOKEN+1)
+#define OCT2 (TOKEN+2)
+#define OCT3 (TOKEN+3)
+#define NOT1 (TOKEN+4)
+#define PCT1 (TOKEN+5)
+#define AND1 (TOKEN+6)
+#define STAR1 (TOKEN+7)
+#define PLUS1 (TOKEN+8)
+#define MINUS1 (TOKEN+9)
+#define ARROW1 (TOKEN+10)
+#define COLON1 (TOKEN+11)
+#define LT1 (TOKEN+12)
+#define LSH1 (TOKEN+13)
+#define EQ1 (TOKEN+14)
+#define RSH1 (TOKEN+15)
+#define GT1 (TOKEN+16)
+#define CIRC1 (TOKEN+17)
+#define OR1 (TOKEN+18)
+#define DEC1 (TOKEN+19)
+#define DEC2 (TOKEN+20)
+#define HEX1 (TOKEN+21)
+#define HEX2 (TOKEN+22)
+#define HEX3 (TOKEN+23)
+#define HEX4 (TOKEN+24)
+#define HEX5 (TOKEN+25)
+#define HEX6 (TOKEN+26)
+#define HEX7 (TOKEN+27)
+#define HEX8 (TOKEN+28)
+#define DBL1 (TOKEN+29)
+#define DBL2 (TOKEN+30)
+#define DBL3 (TOKEN+31)
+#define DBL4 (TOKEN+32)
+#define DBL5 (TOKEN+33)
+#define DOT1 (TOKEN+34)
+#define HDR1 (TOKEN+35)
+#define BIN1 (TOKEN+36)
+
+#define TERMINAL (TOKEN+37)
+
+#endif
+
+/*
+ * quick terminal states grouped together
+ */
+
+#define S_CHRB (TERMINAL+0)
+#define S_COMMENT (TERMINAL+1)
+#define S_EOB (TERMINAL+2)
+#define S_LITBEG (TERMINAL+3)
+#define S_LITEND (TERMINAL+4)
+#define S_LITESC (TERMINAL+5)
+#define S_MACRO (TERMINAL+6)
+#define S_NL (TERMINAL+7)
+#define S_QUAL (TERMINAL+8)
+#define S_SHARP (TERMINAL+9)
+#define S_VS (TERMINAL+10)
+
+/*
+ * and the remaining terminal states
+ */
+
+#define S_CHR (TERMINAL+11)
+#define S_HUH (TERMINAL+12)
+#define S_TOK (TERMINAL+13)
+#define S_TOKB (TERMINAL+14)
+#define S_WS (TERMINAL+15)
+
+#define S_RESERVED (S_HUH)
+
+/*
+ * the last terminal state (for tracing)
+ */
+
+#define LAST (S_WS)
+
+/*
+ * pseudo terminal states
+ */
+
+#define S_EOF (0)
+
+/*
+ * common lex macros
+ *
+ * NOTE: common local variable names assumed
+ */
+
+#define GET(p,c,tp,xp) \
+ do \
+ { \
+ if ((c = GETCHR()) == EOB && pp.in->type == IN_FILE) \
+ FGET(p, c, tp, xp); \
+ } while (0)
+
+#define FGET(p,c,tp,xp) \
+ do \
+ { \
+ if (op > xp + PPTOKSIZ) \
+ { \
+ if (!INCOMMENT(rp) && !(pp.state & (NOTEXT|SKIPCONTROL))) \
+ error(2, "long token truncated"); \
+ op = xp + PPTOKSIZ; \
+ } \
+ if ((pp.in->flags & IN_flush) && pp.level == 1 && !INMACRO(rp) && (!pp.comment || !INCOMMENT(rp)) && (c = op - pp.outbuf) > 0 && *(op - 1) == '\n') \
+ { \
+ PPWRITE(c); \
+ op = tp = pp.outp = pp.outbuf; \
+ } \
+ SYNCIN(); \
+ refill(p); \
+ CACHEIN(); \
+ if ((c = GETCHR()) == EOB) BACKIN(); \
+ } while (0)
+
+#define POP() \
+ do \
+ { \
+ debug((-7, "POP in=%s next=%s state=%s", ppinstr(cur), pptokchr(*prv->nextchr), pplexstr(INDEX(rp)))); \
+ ip = (pp.in = prv)->nextchr; \
+ } while (0)
+
+/*
+ * fsm implementaion globals
+ */
+
+#define fsm _pp_fsmtab
+#define refill _pp_refill
+#define trigraph _pp_trigraph
+
+/*
+ * first index is state, second is char, value is next state
+ * except for fsm[TERMINAL] where second is state+1 for EOF transition
+ */
+
+extern short fsm[TERMINAL+1][MAX+1];
+
+/*
+ * the index is char, value is trigraph value for <?><?><char>, 0 if invalid
+ */
+
+extern char trigraph[MAX+1];
+
+extern void refill(int);
+
+#endif
diff --git a/usr/src/lib/libpp/common/ppincref.c b/usr/src/lib/libpp/common/ppincref.c
new file mode 100644
index 0000000000..336940bb12
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppincref.c
@@ -0,0 +1,49 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common include reference handler
+ * the type arg is inclusive or of PP_SYNC_*
+ */
+
+#include "pplib.h"
+
+void
+ppincref(char* parent, char* file, int line, int type)
+{
+ register struct ppinstk* sp;
+ int level;
+
+ NoP(parent);
+ NoP(line);
+ if (type & PP_SYNC_PUSH)
+ {
+ level = 0;
+ for (sp = pp.in; sp; sp = sp->prev)
+ if (sp->type == IN_FILE)
+ level++;
+ if (level > 0)
+ level--;
+ error(0, "%-*s%s", level * 4, "", file);
+ }
+}
diff --git a/usr/src/lib/libpp/common/ppinput.c b/usr/src/lib/libpp/common/ppinput.c
new file mode 100644
index 0000000000..170e5f5dca
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppinput.c
@@ -0,0 +1,721 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor stacked input stream support
+ */
+
+#include "pplib.h"
+
+
+/*
+ * convert path to native representation
+ */
+
+#if 0
+#include "../../lib/libast/path/pathnative.c" /* drop in 2002 */
+#else
+/* Modified by gisburn 2006-08-18 for OpenSolaris ksh93-integration */
+#include "../../libast/common/path/pathnative.c"
+#endif
+
+static char*
+native(register const char* s)
+{
+ register int c;
+ register struct ppfile* xp;
+ int m;
+ int n;
+
+ static Sfio_t* np;
+ static Sfio_t* qp;
+
+ if (!s)
+ return 0;
+ if (!np && !(np = sfstropen()) || !qp && !(qp = sfstropen()))
+ return (char*)s;
+ n = PATH_MAX;
+ do
+ {
+ m = n;
+ n = pathnative(s, sfstrrsrv(np, m), m);
+ } while (n > m);
+ sfstrseek(np, n, SEEK_CUR);
+ s = (const char*)sfstruse(np);
+ for (;;)
+ {
+ switch (c = *s++)
+ {
+ case 0:
+ break;
+ case '\\':
+ case '"':
+ sfputc(qp, '\\');
+ /*FALLTHROUGH*/
+ default:
+ sfputc(qp, c);
+ continue;
+ }
+ break;
+ }
+ if (!(xp = ppsetfile(sfstruse(qp))))
+ return (char*)s;
+ return xp->name;
+}
+
+/*
+ * push stream onto input stack
+ * used by the PUSH_type macros
+ */
+
+void
+pppush(register int t, register char* s, register char* p, int n)
+{
+ register struct ppinstk* cur;
+
+ PUSH(t, cur);
+ cur->line = error_info.line;
+ cur->file = error_info.file;
+ switch (t)
+ {
+ case IN_FILE:
+ if (pp.option & NATIVE)
+ s = native(s);
+ cur->flags |= IN_newline;
+ cur->fd = n;
+ cur->hide = ++pp.hide;
+ cur->symbol = 0;
+#if CHECKPOINT
+ if ((pp.mode & (DUMP|INIT)) == DUMP)
+ {
+ cur->index = newof(0, struct ppindex, 1, 0);
+ if (pp.lastindex) pp.lastindex->next = cur->index;
+ else pp.firstindex = cur->index;
+ pp.lastindex = cur->index;
+ cur->index->file = pp.original;
+ cur->index->begin = ppoffset();
+ }
+#endif
+ n = 1;
+#if CHECKPOINT
+ if (!(pp.mode & DUMP))
+#endif
+ if (!cur->prev->prev && !(pp.state & COMPILE) && isatty(0))
+ cur->flags |= IN_flush;
+#if ARCHIVE
+ if (pp.member)
+ {
+ switch (pp.member->archive->type & (TYPE_BUFFER|TYPE_CHECKPOINT))
+ {
+ case 0:
+#if CHECKPOINT
+ cur->buflen = pp.member->size;
+#endif
+ p = (cur->buffer = oldof(0, char, 0, pp.member->size + PPBAKSIZ + 1)) + PPBAKSIZ;
+ if (sfseek(pp.member->archive->info.sp, pp.member->offset, SEEK_SET) != pp.member->offset)
+ error(3, "%s: archive seek error", pp.member->archive->name);
+ if (sfread(pp.member->archive->info.sp, p, pp.member->size) != pp.member->size)
+ error(3, "%s: archive read error", pp.member->archive->name);
+ pp.member = 0;
+ break;
+ case TYPE_BUFFER:
+#if CHECKPOINT
+ case TYPE_CHECKPOINT|TYPE_BUFFER:
+ cur->buflen = pp.member->size;
+#endif
+ p = cur->buffer = pp.member->archive->info.buffer + pp.member->offset;
+ cur->flags |= IN_static;
+ pp.member = 0;
+ break;
+#if CHECKPOINT
+ case TYPE_CHECKPOINT:
+ p = cur->buffer = "";
+ cur->flags |= IN_static;
+ break;
+#endif
+ }
+ cur->flags |= IN_eof|IN_newline;
+ cur->fd = -1;
+ }
+ else
+#endif
+ {
+ if (lseek(cur->fd, 0L, SEEK_END) > 0 && !lseek(cur->fd, 0L, SEEK_SET))
+ cur->flags |= IN_regular;
+ errno = 0;
+#if PROTOTYPE
+ if (!(pp.option & NOPROTO) && !(pp.test & TEST_noproto) && ((pp.state & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY || (pp.option & PLUSPLUS) || (pp.mode & EXTERNALIZE)) && (cur->buffer = pppopen(NiL, cur->fd, NiL, NiL, NiL, NiL, (PROTO_HEADER|PROTO_RETAIN)|(((pp.mode & EXTERNALIZE) || (pp.option & PROTOTYPED)) ? PROTO_FORCE : PROTO_PASS)|((pp.mode & EXTERNALIZE) ? PROTO_EXTERNALIZE : 0)|((pp.mode & MARKC) ? PROTO_PLUSPLUS : 0))))
+ {
+ *(p = cur->buffer - 1) = 0;
+ cur->buffer -= PPBAKSIZ;
+ cur->flags |= IN_prototype;
+ cur->fd = -1;
+ }
+ else
+#endif
+ *(p = (cur->buffer = oldof(0, char, 0, PPBUFSIZ + PPBAKSIZ + 1)) + PPBAKSIZ) = 0;
+ }
+ if (pp.incref && !(pp.mode & INIT))
+ (*pp.incref)(error_info.file, s, error_info.line - 1, PP_SYNC_PUSH);
+ if (pp.macref || (pp.option & IGNORELINE))
+ cur->flags |= IN_ignoreline;
+ cur->prefix = pp.prefix;
+ /*FALLTHROUGH*/
+ case IN_BUFFER:
+ case IN_INIT:
+ case IN_RESCAN:
+ pushcontrol();
+ cur->control = pp.control;
+ *pp.control = 0;
+ cur->vendor = pp.vendor;
+ if (cur->type != IN_RESCAN)
+ {
+ if (cur->type == IN_INIT)
+ pp.mode |= MARKHOSTED;
+ error_info.file = s;
+ error_info.line = n;
+ }
+ if (pp.state & HIDDEN)
+ {
+ pp.state &= ~HIDDEN;
+ pp.hidden = 0;
+ if (!(pp.state & NOTEXT) && pplastout() != '\n')
+ ppputchar('\n');
+ }
+ pp.state |= NEWLINE;
+ if (pp.mode & HOSTED) cur->flags |= IN_hosted;
+ else cur->flags &= ~IN_hosted;
+ if (pp.mode & (INIT|MARKHOSTED))
+ {
+ pp.mode |= HOSTED;
+ pp.flags |= PP_hosted;
+ }
+ switch (cur->type)
+ {
+ case IN_FILE:
+ if (!(pp.mode & (INIT|MARKHOSTED)))
+ {
+ pp.mode &= ~HOSTED;
+ pp.flags &= ~PP_hosted;
+ }
+#if CATSTRINGS
+ if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE;
+ else
+#endif
+ if (pp.linesync)
+ (*pp.linesync)(error_info.line, error_info.file);
+#if ARCHIVE && CHECKPOINT
+ if (pp.member)
+ ppload(NiL);
+#endif
+ if (pp.mode & MARKC)
+ {
+ cur->flags |= IN_c;
+ pp.mode &= ~MARKC;
+ if (!(cur->prev->flags & IN_c))
+ {
+ debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp.in), pptokchr(*pp.in->nextchr), pp.in->nextchr));
+ PUSH_BUFFER("C", "extern \"C\" {\n", 1);
+ return;
+ }
+ }
+ else if (cur->prev->flags & IN_c)
+ {
+ debug((-7, "PUSH in=%s next=%s [%s]", ppinstr(pp.in), pptokchr(*pp.in->nextchr), pp.in->nextchr));
+ PUSH_BUFFER("C", "extern \"C++\" {\n", 1);
+ return;
+ }
+ break;
+ case IN_BUFFER:
+ cur->buffer = p = strdup(p);
+ break;
+ default:
+ cur->buffer = p;
+ break;
+ }
+ cur->nextchr = p;
+ break;
+#if DEBUG
+ default:
+ error(PANIC, "use PUSH_<%d>(...) instead of pppush(IN_<%d>, ...)", cur->type, cur->type);
+ break;
+#endif
+ }
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr)));
+}
+
+/*
+ * external buffer push
+ */
+
+void
+ppinput(char* b, char* f, int n)
+{
+ PUSH_BUFFER(f, b, n);
+}
+
+/*
+ * return expanded value of buffer p
+ */
+
+char*
+ppexpand(register char* p)
+{
+ register char* m;
+ register int n;
+ register int c;
+ long restore;
+ char* pptoken;
+ char* ppmactop;
+ struct ppmacstk* nextmacp;
+ struct ppinstk* cur;
+
+ debug((-7, "before expand: %s", p));
+ if (ppmactop = pp.mactop)
+ {
+ nextmacp = pp.macp->next;
+ nextframe(pp.macp, pp.mactop);
+ }
+ restore = pp.state & (COLLECTING|DISABLE|STRIP);
+ pp.state &= ~restore;
+ pp.mode &= ~MARKMACRO;
+ PUSH_STRING(p);
+ cur = pp.in;
+ pp.in->flags |= IN_expand;
+ pptoken = pp.token;
+ n = 2 * MAXTOKEN;
+ pp.token = p = oldof(0, char, 0, n);
+ m = p + MAXTOKEN;
+ for (;;)
+ {
+ if (pplex())
+ {
+ if ((pp.token = pp.toknxt) > m)
+ {
+ c = pp.token - p;
+ p = newof(p, char, n += MAXTOKEN, 0);
+ m = p + n - MAXTOKEN;
+ pp.token = p + c;
+ }
+ if (pp.mode & MARKMACRO)
+ {
+ pp.mode &= ~MARKMACRO;
+ *pp.token++ = MARK;
+ *pp.token++ = 'X';
+ }
+ }
+ else if (pp.in == cur)
+ break;
+ }
+ *pp.token = 0;
+ if (ppmactop)
+ pp.macp->next = nextmacp;
+ debug((-7, "after expand: %s", p));
+ pp.token = pptoken;
+ pp.state |= restore;
+ pp.in = pp.in->prev;
+ return p;
+}
+
+#if CHECKPOINT
+
+#define LOAD_FUNCTION (1<<0)
+#define LOAD_MULTILINE (1<<1)
+#define LOAD_NOEXPAND (1<<2)
+#define LOAD_PREDICATE (1<<3)
+#define LOAD_READONLY (1<<4)
+#define LOAD_VARIADIC (1<<5)
+
+/*
+ * macro definition dump
+ */
+
+static int
+dump(const char* name, char* v, void* handle)
+{
+ register struct ppmacro* mac;
+ register struct ppsymbol* sym = (struct ppsymbol*)v;
+ register int flags;
+
+ NoP(name);
+ NoP(handle);
+ if ((mac = sym->macro) && !(sym->flags & (SYM_BUILTIN|SYM_PREDEFINED)))
+ {
+ ppprintf("%s", sym->name);
+ ppputchar(0);
+ flags = 0;
+ if (sym->flags & SYM_FUNCTION) flags |= LOAD_FUNCTION;
+ if (sym->flags & SYM_MULTILINE) flags |= LOAD_MULTILINE;
+ if (sym->flags & SYM_NOEXPAND) flags |= LOAD_NOEXPAND;
+ if (sym->flags & SYM_PREDICATE) flags |= LOAD_PREDICATE;
+ if (sym->flags & SYM_READONLY) flags |= LOAD_READONLY;
+ if (sym->flags & SYM_VARIADIC) flags |= LOAD_VARIADIC;
+ ppputchar(flags);
+ if (sym->flags & SYM_FUNCTION)
+ {
+ ppprintf("%d", mac->arity);
+ ppputchar(0);
+ if (mac->arity)
+ {
+ ppprintf("%s", mac->formals);
+ ppputchar(0);
+ }
+ }
+ ppprintf("%s", mac->value);
+ ppputchar(0);
+ }
+ return(0);
+}
+
+/*
+ * dump macro definitions for quick loading via ppload()
+ */
+
+void
+ppdump(void)
+{
+ register struct ppindex* ip;
+ unsigned long macro_offset;
+ unsigned long index_offset;
+
+ /*
+ * NOTE: we assume '\0' does not occur in valid preprocessed output
+ */
+
+ ppputchar(0);
+
+ /*
+ * output global flags
+ */
+
+ macro_offset = ppoffset();
+ ppputchar(0);
+
+ /*
+ * output macro definitions
+ */
+
+ hashwalk(pp.symtab, 0, dump, NiL);
+ ppputchar(0);
+
+ /*
+ * output include file index
+ */
+
+ index_offset = ppoffset();
+ ip = pp.firstindex;
+ while (ip)
+ {
+ ppprintf("%s", ip->file->name);
+ ppputchar(0);
+ if (ip->file->guard != INC_CLEAR && ip->file->guard != INC_IGNORE && ip->file->guard != INC_TEST)
+ ppprintf("%s", ip->file->guard->name);
+ ppputchar(0);
+ ppprintf("%lu", ip->begin);
+ ppputchar(0);
+ ppprintf("%lu", ip->end);
+ ppputchar(0);
+ ip = ip->next;
+ }
+ ppputchar(0);
+
+ /*
+ * output offset directory
+ */
+
+ ppprintf("%010lu", macro_offset);
+ ppputchar(0);
+ ppprintf("%010lu", index_offset);
+ ppputchar(0);
+ ppflushout();
+}
+
+/*
+ * load text and macro definitions from a previous ppdump()
+ * s is the string argument from the pragma (including quotes)
+ */
+
+void
+ppload(register char* s)
+{
+ register char* b;
+ register Sfio_t* sp;
+ int m;
+ char* g;
+ char* t;
+ unsigned long n;
+ unsigned long p;
+ unsigned long macro_offset;
+ unsigned long index_offset;
+ unsigned long file_offset;
+ unsigned long file_size;
+ unsigned long keep_begin;
+ unsigned long keep_end;
+ unsigned long skip_end;
+ unsigned long next_begin;
+ unsigned long next_end;
+ struct ppfile* fp;
+ struct ppsymbol* sym;
+ struct ppmacro* mac;
+
+ char* ip = 0;
+
+ pp.mode |= LOADING;
+ if (!(pp.state & STANDALONE))
+ error(3, "checkpoint load in standalone mode only");
+#if ARCHIVE
+ if (pp.member)
+ {
+ sp = pp.member->archive->info.sp;
+ file_offset = pp.member->offset;
+ file_size = pp.member->size;
+ if (sfseek(sp, file_offset + 22, SEEK_SET) != file_offset + 22 || !(s = sfgetr(sp, '\n', 1)))
+ error(3, "checkpoint magic error");
+ }
+ else
+#endif
+ {
+ if (pp.in->type != IN_FILE)
+ error(3, "checkpoint load from files only");
+ if (pp.in->flags & IN_prototype)
+ pp.in->fd = pppdrop(pp.in->buffer + PPBAKSIZ);
+ file_offset = 0;
+ if (pp.in->fd >= 0)
+ {
+ if (!(sp = sfnew(NiL, NiL, SF_UNBOUND, pp.in->fd, SF_READ)))
+ error(3, "checkpoint read error");
+ file_size = sfseek(sp, 0L, SEEK_END);
+ }
+ else
+ {
+ file_size = pp.in->buflen;
+ if (!(sp = sfnew(NiL, pp.in->buffer + ((pp.in->flags & IN_static) ? 0 : PPBAKSIZ), file_size, -1, SF_READ|SF_STRING)))
+ error(3, "checkpoint read error");
+ }
+ }
+ if (!streq(s, pp.checkpoint))
+ error(3, "checkpoint version %s does not match %s", s, pp.checkpoint);
+
+ /*
+ * get the macro and index offsets
+ */
+
+ p = file_offset + file_size - 22;
+ if ((n = sfseek(sp, p, SEEK_SET)) != p)
+ error(3, "checkpoint directory seek error");
+ if (!(t = sfreserve(sp, 22, 0)))
+ error(3, "checkpoint directory read error");
+ macro_offset = file_offset + strtol(t, &t, 10);
+ index_offset = file_offset + strtol(t + 1, NiL, 10);
+
+ /*
+ * read the include index
+ */
+
+ if (sfseek(sp, index_offset, SEEK_SET) != index_offset)
+ error(3, "checkpoint index seek error");
+ if (!(s = sfreserve(sp, n - index_offset, 0)))
+ error(3, "checkpoint index read error");
+ if (sfset(sp, 0, 0) & SF_STRING)
+ b = s;
+ else if (!(b = ip = memdup(s, n - index_offset)))
+ error(3, "checkpoint index alloc error");
+
+ /*
+ * loop on the index and copy the non-ignored chunks to the output
+ */
+
+ ppcheckout();
+ p = PPBUFSIZ - (pp.outp - pp.outbuf);
+ keep_begin = 0;
+ keep_end = 0;
+ skip_end = 0;
+ while (*b)
+ {
+ fp = ppsetfile(b);
+ while (*b++);
+ g = b;
+ while (*b++);
+ next_begin = strtol(b, &t, 10);
+ next_end = strtol(t + 1, &t, 10);
+if (pp.test & 0x0200) error(2, "%s: %s p=%lu next=<%lu,%lu> keep=<%lu,%lu> skip=<-,%lu> guard=%s", keyname(X_CHECKPOINT), fp->name, p, next_begin, next_end, keep_begin, keep_end, skip_end, fp->guard == INC_CLEAR ? "[CLEAR]" : fp->guard == INC_TEST ? "[TEST]" : fp->guard == INC_IGNORE ? "[IGNORE]" : fp->guard->name);
+ b = t + 1;
+ if (next_begin >= skip_end)
+ {
+ if (!ppmultiple(fp, INC_TEST))
+ {
+if (pp.test & 0x0100) error(2, "%s: %s IGNORE", keyname(X_CHECKPOINT), fp->name);
+ if (!keep_begin && skip_end < next_begin)
+ keep_begin = skip_end;
+ if (keep_begin)
+ {
+ flush:
+ if (sfseek(sp, file_offset + keep_begin, SEEK_SET) != file_offset + keep_begin)
+ error(3, "checkpoint data seek error");
+ n = next_begin - keep_begin;
+if (pp.test & 0x0100) error(2, "%s: copy <%lu,%lu> n=%lu p=%lu", keyname(X_CHECKPOINT), keep_begin, next_begin - 1, n, p);
+ while (n > p)
+ {
+ if (sfread(sp, pp.outp, p) != p)
+ error(3, "checkpoint data read error");
+ PPWRITE(PPBUFSIZ);
+ pp.outp = pp.outbuf;
+ n -= p;
+ p = PPBUFSIZ;
+ }
+ if (n)
+ {
+ if (sfread(sp, pp.outp, n) != n)
+ error(3, "checkpoint data read error");
+ pp.outp += n;
+ p -= n;
+ }
+ keep_begin = 0;
+ if (keep_end <= next_end)
+ keep_end = 0;
+ }
+ skip_end = next_end;
+ }
+ else if (!keep_begin)
+ {
+ if (skip_end)
+ {
+ keep_begin = skip_end;
+ skip_end = 0;
+ }
+ else keep_begin = next_begin;
+ if (keep_end < next_end)
+ keep_end = next_end;
+ }
+ }
+ if (*g && fp->guard != INC_IGNORE)
+ fp->guard = ppsymset(pp.symtab, g);
+ }
+ if (keep_end)
+ {
+ if (!keep_begin)
+ keep_begin = skip_end > next_end ? skip_end : next_end;
+ next_begin = next_end = keep_end;
+ g = b;
+ goto flush;
+ }
+if (pp.test & 0x0100) error(2, "%s: loop", keyname(X_CHECKPOINT));
+
+ /*
+ * read the compacted definitions
+ */
+
+ if (sfseek(sp, macro_offset, SEEK_SET) != macro_offset)
+ error(3, "checkpoint macro seek error");
+ if (!(s = sfreserve(sp, index_offset - macro_offset, 0)))
+ error(3, "checkpoint macro read error");
+
+ /*
+ * read the flags
+ */
+
+ while (*s)
+ {
+#if _options_dumped_
+ if (streq(s, "OPTION")) /* ... */;
+ else
+#endif
+ error(3, "%-.48s: unknown flags in checkpoint file", s);
+ }
+ s++;
+
+ /*
+ * unpack and enter the definitions
+ */
+
+ while (*s)
+ {
+ b = s;
+ while (*s++);
+ m = *s++;
+ sym = ppsymset(pp.symtab, b);
+ if (sym->macro)
+ {
+ if (m & LOAD_FUNCTION)
+ {
+ if (*s++ != '0')
+ while (*s++);
+ while (*s++);
+ }
+if (pp.test & 0x1000) error(2, "checkpoint SKIP %s=%s [%s]", sym->name, s, sym->macro->value);
+ while (*s++);
+ }
+ else
+ {
+ ppfsm(FSM_MACRO, b);
+ sym->flags = 0;
+ if (m & LOAD_FUNCTION) sym->flags |= SYM_FUNCTION;
+ if (m & LOAD_MULTILINE) sym->flags |= SYM_MULTILINE;
+ if (m & LOAD_NOEXPAND) sym->flags |= SYM_NOEXPAND;
+ if (m & LOAD_PREDICATE) sym->flags |= SYM_PREDICATE;
+ if (m & LOAD_READONLY) sym->flags |= SYM_READONLY;
+ if (m & LOAD_VARIADIC) sym->flags |= SYM_VARIADIC;
+ mac = sym->macro = newof(0, struct ppmacro, 1, 0);
+ if (sym->flags & SYM_FUNCTION)
+ {
+ for (n = 0; *s >= '0' && *s <= '9'; n = n * 10 + *s++ - '0');
+ if (*s++) error(3, "%-.48: checkpoint macro arity botched", sym->name);
+ if (mac->arity = n)
+ {
+ b = s;
+ while (*s++);
+ mac->formals = (char*)memcpy(oldof(0, char, 0, s - b), b, s - b);
+ }
+ }
+ b = s;
+ while (*s++);
+ mac->size = s - b - 1;
+ mac->value = (char*)memcpy(oldof(0, char, 0, mac->size + 1), b, mac->size + 1);
+if (pp.test & 0x1000) error(2, "checkpoint LOAD %s=%s", sym->name, mac->value);
+ }
+ }
+
+ /*
+ * we are now at EOF
+ */
+
+ if (ip)
+ {
+ pp.in->fd = -1;
+ free(ip);
+ }
+#if ARCHIVE
+ if (pp.member) pp.member = 0;
+ else
+#endif
+ {
+ sfclose(sp);
+ pp.in->flags |= IN_eof|IN_newline;
+ pp.in->nextchr = pp.in->buffer + PPBAKSIZ;
+ *pp.in->nextchr++ = 0;
+ *pp.in->nextchr = 0;
+ }
+ pp.mode &= ~LOADING;
+}
+
+#endif
diff --git a/usr/src/lib/libpp/common/ppkey.c b/usr/src/lib/libpp/common/ppkey.c
new file mode 100644
index 0000000000..6dfe481cc4
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppkey.c
@@ -0,0 +1,118 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor C language reserved keyword token table
+ * for use by PP_COMPILE
+ *
+ * "-" keywords entered without SYM_KEYWORD
+ * "+" keywords entered without SYM_KEYWORD unless PP_PLUSPLUS was set
+ * upper case are pseudo keywords for PP_RESERVED token classes
+ */
+
+#include "pplib.h"
+#include "ppkey.h"
+
+struct ppkeyword ppkey[] =
+{
+ "auto", T_AUTO,
+ "break", T_BREAK,
+ "case", T_CASE,
+ "char", T_CHAR,
+ "continue", T_CONTINUE,
+ "default", T_DEFAULT,
+ "do", T_DO,
+ "double", T_DOUBLE_T,
+ "else", T_ELSE,
+ "extern", T_EXTERN,
+ "float", T_FLOAT_T,
+ "for", T_FOR,
+ "goto", T_GOTO,
+ "if", T_IF,
+ "int", T_INT,
+ "long", T_LONG,
+ "register", T_REGISTER,
+ "return", T_RETURN,
+ "short", T_SHORT,
+ "sizeof", T_SIZEOF,
+ "static", T_STATIC,
+ "struct", T_STRUCT,
+ "switch", T_SWITCH,
+ "typedef", T_TYPEDEF,
+ "union", T_UNION,
+ "unsigned", T_UNSIGNED,
+ "while", T_WHILE,
+ "-const", T_CONST,
+ "-enum", T_ENUM,
+ "-signed", T_SIGNED,
+ "-void", T_VOID,
+ "-volatile", T_VOLATILE,
+ "+asm", T_ASM,
+ "+class", T_CLASS,
+ "+delete", T_DELETE,
+ "+friend", T_FRIEND,
+ "+inline", T_INLINE,
+ "+new", T_NEW,
+ "+operator", T_OPERATOR,
+ "+overload", T_OVERLOAD,
+ "+private", T_PRIVATE,
+ "+public", T_PUBLIC,
+ "+this", T_THIS,
+ "+virtual", T_VIRTUAL,
+ "-and", T_ANDAND,
+ "-and_eq", T_ANDEQ,
+ "-bitand", '&',
+ "-bitor", '|',
+ "-bool", T_BOOL,
+ "-catch", T_CATCH,
+ "-compl", '~',
+ "-const_cast", T_CONST_CAST,
+ "-dynamic_cast",T_DYNAMIC_CAST,
+ "-explicit", T_EXPLICIT,
+ "-false", T_FALSE,
+ "-mutable", T_MUTABLE,
+ "-namespace", T_NAMESPACE,
+ "-not", '!',
+ "-not_eq", T_NE,
+ "-or", T_OROR,
+ "-or_eq", T_OREQ,
+ "-protected", T_PROTECTED,
+ "-reinterpret_cast", T_REINTERPRET_CAST,
+ "-static_cast", T_STATIC_CAST,
+ "-template", T_TEMPLATE,
+ "-throw", T_THROW,
+ "-true", T_TRUE,
+ "-try", T_TRY,
+ "-typeid", T_TYPEID,
+ "-using", T_USING,
+ "-wchar_t", T_WCHAR_T,
+ "-xor", '^',
+ "-xor_eq", T_XOREQ,
+ "-int64", T_INT64,
+ "-NOISES", T_NOISES,
+ "-NOISE", T_NOISE,
+ "-GROUP", T_X_GROUP,
+ "-LINE", T_X_LINE,
+ "-STATEMENT", T_X_STATEMENT,
+ 0, 0, 0
+};
diff --git a/usr/src/lib/libpp/common/ppkey.h b/usr/src/lib/libpp/common/ppkey.h
new file mode 100644
index 0000000000..95f89e52c1
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppkey.h
@@ -0,0 +1,146 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor C language keyword token values
+ * handles classic, ANSI and C++
+ * additional non-standard keyword tokens are
+ * crammed into T_NOISE and T_X_*
+ */
+
+#ifndef _PPKEY_H
+#define _PPKEY_H
+
+/*
+ * NOTE: preserve the ranges for is*()
+ */
+
+#define ppisnoise(x) ((x)>=T_NOISE&&(x)<T_KEYWORD)
+
+/*
+ * classic
+ */
+
+#define T_AUTO (T_TOKEN+0)
+#define T_BREAK (T_TOKEN+1)
+#define T_CASE (T_TOKEN+2)
+#define T_CHAR (T_TOKEN+3)
+#define T_CONTINUE (T_TOKEN+4)
+#define T_DEFAULT (T_TOKEN+5)
+#define T_DO (T_TOKEN+6)
+#define T_DOUBLE_T (T_TOKEN+7)
+#define T_ELSE (T_TOKEN+8)
+#define T_EXTERN (T_TOKEN+9)
+#define T_FLOAT_T (T_TOKEN+10)
+#define T_FOR (T_TOKEN+11)
+#define T_GOTO (T_TOKEN+12)
+#define T_IF (T_TOKEN+13)
+#define T_INT (T_TOKEN+14)
+#define T_LONG (T_TOKEN+15)
+#define T_REGISTER (T_TOKEN+16)
+#define T_RETURN (T_TOKEN+17)
+#define T_SHORT (T_TOKEN+18)
+#define T_SIZEOF (T_TOKEN+19)
+#define T_STATIC (T_TOKEN+20)
+#define T_STRUCT (T_TOKEN+21)
+#define T_SWITCH (T_TOKEN+22)
+#define T_TYPEDEF (T_TOKEN+23)
+#define T_UNION (T_TOKEN+24)
+#define T_UNSIGNED (T_TOKEN+25)
+#define T_WHILE (T_TOKEN+26)
+
+/*
+ * ANSI
+ */
+
+#define T_CONST (T_TOKEN+27)
+#define T_ENUM (T_TOKEN+28)
+#define T_SIGNED (T_TOKEN+29)
+#define T_VOID (T_TOKEN+30)
+#define T_VOLATILE (T_TOKEN+31)
+
+/*
+ * C++
+ */
+
+#define T_ASM (T_TOKEN+32)
+#define T_BOOL (T_TOKEN+33)
+#define T_CATCH (T_TOKEN+34)
+#define T_CLASS (T_TOKEN+35)
+#define T_CONST_CAST (T_TOKEN+36)
+#define T_DELETE (T_TOKEN+37)
+#define T_DYNAMIC_CAST (T_TOKEN+38)
+#define T_EXPLICIT (T_TOKEN+39)
+#define T_FALSE (T_TOKEN+40)
+#define T_FRIEND (T_TOKEN+41)
+#define T_INLINE (T_TOKEN+42)
+#define T_MUTABLE (T_TOKEN+43)
+#define T_NAMESPACE (T_TOKEN+44)
+#define T_NEW (T_TOKEN+45)
+#define T_OPERATOR (T_TOKEN+46)
+#define T_OVERLOAD (T_TOKEN+47)
+#define T_PRIVATE (T_TOKEN+48)
+#define T_PROTECTED (T_TOKEN+49)
+#define T_PUBLIC (T_TOKEN+50)
+#define T_REINTERPRET_CAST (T_TOKEN+51)
+#define T_STATIC_CAST (T_TOKEN+52)
+#define T_TEMPLATE (T_TOKEN+53)
+#define T_THIS (T_TOKEN+54)
+#define T_THROW (T_TOKEN+55)
+#define T_TRUE (T_TOKEN+56)
+#define T_TRY (T_TOKEN+57)
+#define T_TYPEID (T_TOKEN+58)
+#define T_USING (T_TOKEN+59)
+#define T_VIRTUAL (T_TOKEN+60)
+#define T_WCHAR_T (T_TOKEN+61)
+
+/*
+ * future
+ */
+
+#define T_INT64 (T_TOKEN+62)
+
+/*
+ * non-standard
+ */
+
+#define T_BUILTIN (T_TOKEN+63)
+#define T_NOISES (T_TOKEN+64)
+#define T_NOISE (T_TOKEN+65)
+#define T_X_GROUP (T_TOKEN+66)
+#define T_X_LINE (T_TOKEN+67)
+#define T_X_STATEMENT (T_TOKEN+68)
+
+/*
+ * first available keyword token value
+ */
+
+#define T_KEYWORD (T_TOKEN+69)
+
+/*
+ * implementation globals
+ */
+
+extern struct ppkeyword ppkey[];
+
+#endif
diff --git a/usr/src/lib/libpp/common/pplex.c b/usr/src/lib/libpp/common/pplex.c
new file mode 100644
index 0000000000..364854d8ae
--- /dev/null
+++ b/usr/src/lib/libpp/common/pplex.c
@@ -0,0 +1,2441 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor lexical analyzer
+ * standalone and tokenizing lexer combined in one source
+ * define CPP=1 for standalone
+ */
+
+#include "pplib.h"
+#include "ppfsm.h"
+
+#if CPP
+
+/*
+ * standalone entry point
+ */
+
+#define PPCPP_T void
+
+#define START QUICK
+#define INMACRO(x) INQMACRO(x)
+#define DOSTRIP() (st&STRIP)
+
+#if DEBUG & TRACE_debug
+static int hit[LAST-TERMINAL+2];
+#endif
+
+#define BACKIN() (ip--)
+#define BACKOUT() (op=tp)
+#define CACHE() do{CACHEINX();CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
+#define CACHEIN() do{CACHEINX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
+#define CACHEINX() do{ip=pp.in->nextchr;}while(0)
+#define CACHEOUT() do{CACHEOUTX();st=pp.state;if(!pp.hidden)spliced=0;}while(0)
+#define CACHEOUTX() do{tp=op=pp.outp;xp=pp.oute;if(sp)sp=op;}while(0)
+#define GETCHR() (*(unsigned char*)ip++)
+#define LASTCHR() (*(ip-1))
+#define LASTOUT() ((op>pp.outbuf)?*(op-1):pp.lastout)
+#define SKIPIN() (ip++)
+#define PUTCHR(c) (*op++=(c))
+#define SETCHR(c) (*op=(c))
+#define SYNC() do{SYNCINX();SYNCOUTX();pp.state=st;}while(0)
+#define SYNCIN() do{SYNCINX();pp.state=st;}while(0)
+#define SYNCINX() do{pp.in->nextchr=ip;}while(0)
+#define SYNCOUT() do{SYNCOUTX();pp.state=st;}while(0)
+#define SYNCOUTX() do{if(sp)op=tp=sp;pp.outp=op;}while(0)
+#define UNGETCHR(c) (*--ip=(c))
+
+#define PPCHECKOUT() do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0)
+#define PPCHECKOUTSP() do{if(op>xp){if(sp)op=sp;else{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}}}while(0)
+#define PPCHECKOUTTP() do{if(op>xp){{PPWRITE(PPBUFSIZ);if(pp.outbuf==pp.outb){pp.outbuf+=PPBUFSIZ;xp=pp.oute+=PPBUFSIZ;}else{pp.outbuf-=PPBUFSIZ;memcpy(pp.outbuf,xp,op-xp);xp=pp.oute-=PPBUFSIZ;op-=2*PPBUFSIZ;}}tp=op;}}while(0)
+
+#define PPSYNCLINE() do { \
+ if ((st & (ADD|HIDDEN)) && !(*pp.control & SKIP)) \
+ { \
+ if (spliced) \
+ { \
+ error_info.line += spliced; \
+ spliced = 0; \
+ } \
+ else \
+ { \
+ if (st & ADD) \
+ { \
+ st &= ~ADD; \
+ m = pp.addp - pp.addbuf; \
+ pp.addp = pp.addbuf; \
+ memcpy(op, pp.addbuf, m); \
+ op += m; \
+ PPCHECKOUT(); \
+ } \
+ if (pp.linesync) \
+ { \
+ if ((st & SYNCLINE) || pp.hidden >= MAXHIDDEN) \
+ { \
+ pp.hidden = 0; \
+ st &= ~(HIDDEN|SYNCLINE); \
+ if (error_info.line) \
+ { \
+ if (LASTOUT() != '\n') \
+ PUTCHR('\n'); \
+ SYNCOUT(); \
+ (*pp.linesync)(error_info.line, error_info.file); \
+ CACHEOUT(); \
+ } \
+ } \
+ else \
+ { \
+ m = pp.hidden; \
+ pp.hidden = 0; \
+ st &= ~HIDDEN; \
+ while (m-- > 0) \
+ PUTCHR('\n'); \
+ } \
+ } \
+ else \
+ { \
+ pp.hidden = 0; \
+ st &= ~HIDDEN; \
+ PUTCHR('\n'); \
+ } \
+ } \
+ } \
+ } while (0)
+
+#if POOL
+
+/*
+ * <wait.h> is poison here so pool moved to the end
+ */
+
+static void poolstatus(void);
+static void pool(void);
+
+#endif
+
+#else
+
+/*
+ * return next pp token
+ *
+ * NOTE: pp.token points to at least MAXTOKEN*2 chars and is
+ * truncated back to MAXTOKEN on EOB
+ */
+
+#define PPCPP_T int
+#define ppcpp pplex
+
+#define START TOKEN
+#define INMACRO(x) INTMACRO(x)
+#define DOSTRIP() ((st&STRIP)||pp.level==1&&(st&(COMPILE|JOINING))==COMPILE&&!(pp.option&PRESERVE))
+
+#define st pp.state
+#define tp pp.token
+#define xp &pp.token[MAXTOKEN]
+
+#define BACKIN() (ip--)
+#define BACKOUT() (op=pp.token)
+#define CACHE() do{CACHEIN();CACHEOUT();}while(0)
+#define CACHEIN() (ip=pp.in->nextchr)
+#define CACHEOUT() (op=pp.token)
+#define GETCHR() (*(unsigned char*)ip++)
+#define LASTCHR() (*(ip-1))
+#define PUTCHR(c) (*op++=(c))
+#define SETCHR(c) (*op=(c))
+#define SKIPIN() (ip++)
+#define SYNC() do{SYNCIN();SYNCOUT();}while(0)
+#define SYNCIN() (pp.in->nextchr=ip)
+#define SYNCOUT() (pp.toknxt=op)
+#define UNGETCHR(c) (*--ip=(c))
+
+#endif
+
+PPCPP_T
+ppcpp(void)
+{
+ register short* rp;
+ register char* ip;
+ register int state;
+ register int c;
+ register char* op;
+ char* bp;
+ int n;
+ int m;
+ int quot;
+ int quotquot;
+ int comdelim = 0;
+ int comstart = 0;
+ int comwarn = 0;
+ char* s;
+ struct ppsymbol* sym;
+#if CPP
+ register long st;
+ char* tp;
+ char* xp;
+ char* sp = 0;
+ int qual = 0;
+ int spliced = 0;
+#else
+ int qual;
+#endif
+
+#if CPP
+#if POOL
+ fsm_pool:
+#endif
+#else
+ count(pplex);
+#endif
+ error_info.indent++;
+ pp.level++;
+ CACHE();
+#if !CPP
+ fsm_top:
+ qual = 0;
+#endif
+ fsm_start:
+#if CPP
+ PPCHECKOUTSP();
+ tp = op;
+#endif
+ state = START;
+ fsm_begin:
+ bp = ip;
+ do
+ {
+ rp = fsm[state];
+ fsm_get:
+ while (!(state = rp[c = GETCHR()]));
+ fsm_next:
+ ;
+ } while (state > 0);
+ if (((state = ~state) != S_COMMENT || pp.comment || c == '/' && !INCOMMENT(rp)) && (n = ip - bp - 1) > 0)
+ {
+ ip = bp;
+#if CPP
+ if (op == tp && (st & (ADD|HIDDEN)) && !(st & PASSTHROUGH))
+ switch (TERM(state))
+ {
+ case S_SHARP:
+ break;
+ case S_CHRB:
+ case S_NL:
+ if (*ip == '\n')
+ break;
+ /*FALLTHROUGH*/
+ default:
+ PPSYNCLINE();
+ tp = op;
+ break;
+ }
+#endif
+ MEMCPY(op, ip, n);
+ ip++;
+ }
+ count(terminal);
+#if CPP && (DEBUG & TRACE_debug)
+ hit[(state & SPLICE) ? (elementsof(hit) - 1) : (TERM(state) - TERMINAL)]++;
+#endif
+ fsm_terminal:
+ debug((-9, "TERM %s > %s%s%s |%-*.*s|%s|", pplexstr(INDEX(rp)), pplexstr(state), (st & NEWLINE) ? "|NEWLINE" : "", (st & SKIPCONTROL) ? "|SKIP" : "", op - tp, op - tp, tp, pptokchr(c)));
+ switch (TERM(state))
+ {
+
+#if !CPP
+ case S_CHR:
+ PUTCHR(c);
+ break;
+#endif
+
+ case S_CHRB:
+ BACKIN();
+#if CPP
+ st &= ~NEWLINE;
+ pp.in->flags |= IN_tokens;
+ count(token);
+ goto fsm_start;
+#else
+ c = *tp;
+ break;
+#endif
+
+ case S_COMMENT:
+ switch (c)
+ {
+ case '\n':
+ if (!INCOMMENTXX(rp))
+ {
+ qual = 0;
+ if (!comstart) comstart = comdelim = error_info.line;
+ error_info.line++;
+ if (pp.comment) PUTCHR(c);
+ else BACKOUT();
+#if CPP
+ rp = fsm[COM2];
+ bp = ip;
+ goto fsm_get;
+#else
+ state = COM2;
+ goto fsm_begin;
+#endif
+ }
+ else if (comwarn < 0 && !(pp.mode & HOSTED))
+ error(1, "/* appears in // comment");
+ break;
+ case '*':
+ if (!comwarn && !(pp.mode & HOSTED))
+ {
+ if (INCOMMENTXX(rp)) comwarn = -1;
+ else if (comstart && comstart != error_info.line)
+ {
+ if (qual || comdelim < error_info.line - 1)
+ {
+ error(1, "/* appears in /* ... */ comment starting at line %d", comstart);
+ comwarn = 1;
+ }
+ else comdelim = error_info.line;
+ }
+ }
+ fsm_comment:
+ PUTCHR(c);
+#if CPP
+ rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
+ bp = ip;
+ goto fsm_get;
+#else
+ state = INCOMMENTXX(rp) ? COM5 : COM3;
+ goto fsm_begin;
+#endif
+ case '/':
+ if (!INCOMMENT(rp))
+ {
+ if (!(pp.mode & HOSTED))
+ error(1, "*/ appears outside of comment");
+ BACKIN();
+#if CPP
+ st &= ~NEWLINE;
+ pp.in->flags |= IN_tokens;
+ count(token);
+ goto fsm_start;
+#else
+ c = '*';
+ if (!pp.comment) PUTCHR(c);
+ goto fsm_token;
+#endif
+ }
+ else if (INCOMMENTXX(rp))
+ {
+ if (!(pp.mode & HOSTED))
+ {
+ if (comwarn < 0) comwarn = 0;
+ else if (!comwarn)
+ {
+ comwarn = 1;
+ error(1, "*/ appears in // comment");
+ }
+ }
+ goto fsm_comment;
+ }
+ break;
+ case EOF:
+ BACKIN();
+ if (!(pp.mode & HOSTED))
+ {
+ if (comstart) error(2, "unterminated /* ... */ comment starting at line %d", comstart);
+ else if (INCOMMENTXX(rp)) error(2, "unterminated // ... comment");
+ else error(2, "unterminated /* ... */ comment");
+ }
+ break;
+ }
+#if CPP
+ if (!pp.comment || sp)
+ {
+#if COMPATIBLE
+ if (!(pp.state & COMPATIBILITY) || *bp == ' ' || *bp == '\t')
+#endif
+ {
+ BACKOUT();
+ PUTCHR(' ');
+ tp = op;
+ }
+ }
+ else if (pp.in->type & IN_TOP)
+#else
+ if (pp.comment && !(st & (COLLECTING|DIRECTIVE|JOINING)) && !(*pp.control & SKIP) && (pp.in->type & IN_TOP))
+#endif
+ {
+ st &= ~HIDDEN;
+ pp.hidden = 0;
+ *(op - (c != '\n')) = 0;
+ m = (op - (c != '\n') - tp > MAXTOKEN - 6) ? (error_info.line - MAXHIDDEN) : 0;
+ BACKOUT();
+ SYNC();
+ while (*tp != '/') tp++;
+ (*pp.comment)(c == '\n' ? "//" : "/*", tp + 2, c == '\n' ? "" : (st & HEADER) ? "*/\n" : "*/", comstart ? comstart : error_info.line);
+ CACHE();
+ comstart = m;
+ }
+ if (comstart)
+ {
+ st |= HIDDEN;
+ pp.hidden += error_info.line - comstart;
+ comstart = 0;
+ }
+ qual = comwarn = comdelim = 0;
+ BACKOUT();
+ if (c == '\n') goto fsm_newline;
+ if ((st & PASSTHROUGH) && ((st & (HIDDEN|NEWLINE)) || *ip == '\n'))
+ {
+ if (*ip == '\n')
+ ip++;
+ goto fsm_newline;
+ }
+#if COMPATIBLE
+ if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
+#endif
+#if !CPP
+ if (pp.level > 1 && !(st & (NOSPACE|SKIPCONTROL)))
+ {
+#if COMPATIBLE
+ c = ((st & (COMPATIBILITY|DEFINITION)) == ((COMPATIBILITY|DEFINITION))) ? '\t' : ' ';
+#else
+ c = ' ';
+#endif
+ goto fsm_return;
+ }
+#endif
+ goto fsm_start;
+
+ case S_EOB:
+ if (c)
+ {
+ if (state = fsm[TERMINAL][INDEX(rp)+1])
+ goto fsm_terminal;
+#if CPP
+#if POOL
+ if (pp.pool.input)
+ {
+ BACKIN();
+ SYNC();
+ pool();
+ CACHE();
+ goto fsm_pool;
+ }
+#endif
+ SYNCOUT();
+ return;
+#else
+ BACKIN();
+ c = 0;
+ goto fsm_return;
+#endif
+ }
+ {
+ register struct ppinstk* cur = pp.in;
+ register struct ppinstk* prv = pp.in->prev;
+
+#if CPP
+ if (sp) op = sp;
+#endif
+ switch (cur->type)
+ {
+ case IN_BUFFER:
+ case IN_INIT:
+ case IN_RESCAN:
+#if CPP
+ if (prv)
+#else
+ if (!(st & PASSEOF) && prv)
+#endif
+ {
+ if (cur->type == IN_RESCAN || cur->type == IN_BUFFER)
+ {
+ fsm_pop:
+#if PROTOTYPE
+ if (cur->flags & IN_prototype)
+ pppclose(cur->buffer + PPBAKSIZ);
+ else
+#endif
+ if (!(cur->flags & IN_static))
+ free(cur->buffer);
+ }
+ while (pp.control-- != cur->control)
+ error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
+ st |= NEWLINE;
+ error_info.file = cur->file;
+ error_info.line = cur->line;
+ pp.hidden = 0;
+#if CPP
+ spliced = 0;
+#endif
+ if (cur->flags & IN_hosted)
+ {
+ pp.mode |= HOSTED;
+ pp.flags |= PP_hosted;
+ }
+ else
+ {
+ pp.mode &= ~HOSTED;
+ pp.flags &= ~PP_hosted;
+ }
+#if !CPP && CATSTRINGS
+ if (st & JOINING) st |= HIDDEN|SYNCLINE;
+ else
+#endif
+ {
+ st &= ~(HIDDEN|SYNCLINE);
+ switch (cur->type)
+ {
+ case IN_BUFFER:
+ case IN_INIT:
+ if (!prv->prev) break;
+ /*FALLTHROUGH*/
+ case IN_FILE:
+ case IN_RESCAN:
+ if (prv->type == IN_FILE || cur->type == IN_FILE && (prv->type == IN_RESCAN || prv->type == IN_MULTILINE))
+ {
+ if (pp.linesync && (cur->type != IN_RESCAN || (cur->flags & IN_sync)))
+ {
+ POP();
+ SYNCOUT();
+ (*pp.linesync)(error_info.line, error_info.file);
+ CACHEOUT();
+ prv = pp.in;
+ }
+ }
+#if DEBUG
+ else if (!prv->prev)
+ {
+ /*UNDENT*/
+ c = 0;
+#if DEBUG & TRACE_count
+ if (pp.test & TEST_count)
+ {
+ c = 1;
+ sfprintf(sfstderr, "\n");
+ sfprintf(sfstderr, "%7d: pplex calls\n", pp.counter.pplex);
+ sfprintf(sfstderr, "%7d: terminal states\n", pp.counter.terminal);
+ sfprintf(sfstderr, "%7d: emitted tokens\n", pp.counter.token);
+ sfprintf(sfstderr, "%7d: input stream pushes\n", pp.counter.push);
+ sfprintf(sfstderr, "%7d: macro candidates\n", pp.counter.candidate);
+ sfprintf(sfstderr, "%7d: macro expansions\n", pp.counter.macro);
+ sfprintf(sfstderr, "%7d: function macros\n", pp.counter.function);
+ }
+#endif
+#if CPP && (DEBUG & TRACE_debug)
+ if (pp.test & TEST_hit)
+ {
+ c = 1;
+ sfprintf(sfstderr, "\n");
+ if (hit[elementsof(hit) - 1])
+ sfprintf(sfstderr, "%7d: SPLICE\n", hit[elementsof(hit) - 1]);
+ for (n = 0; n < elementsof(hit) - 1; n++)
+ if (hit[n])
+ sfprintf(sfstderr, "%7d: %s\n", hit[n], pplexstr(TERMINAL + n));
+ }
+#endif
+ if (pp.test & (TEST_hashcount|TEST_hashdump))
+ {
+ c = 1;
+ sfprintf(sfstderr, "\n");
+ hashdump(NiL, (pp.test & TEST_hashdump) ? HASH_BUCKET : 0);
+ }
+ if (c) sfprintf(sfstderr, "\n");
+ /*INDENT*/
+ }
+#endif
+ break;
+ }
+ }
+#if CHECKPOINT
+ if (cur->index)
+ {
+ SYNCOUT();
+ cur->index->end = ppoffset();
+ cur->index = 0;
+ CACHEOUT();
+ }
+#endif
+ POP();
+ bp = ip;
+ tp = op;
+ goto fsm_get;
+ }
+ c = EOF;
+ break;
+ case IN_COPY:
+ if (prv)
+ {
+ error_info.line = cur->line;
+ if (!(prv->symbol->flags & SYM_MULTILINE))
+ prv->symbol->flags |= SYM_DISABLED;
+ POP();
+ bp = ip;
+ goto fsm_get;
+ }
+ c = EOF;
+ break;
+ case IN_EXPAND:
+ if (prv)
+ {
+ error_info.line = cur->line;
+ free(cur->buffer);
+ POP();
+ bp = ip;
+ goto fsm_get;
+ }
+ c = EOF;
+ break;
+ case IN_FILE:
+ FGET(c, c, tp, xp);
+ if (c == EOB)
+ {
+#if CPP
+ if ((st & (NOTEXT|HIDDEN)) == HIDDEN && LASTOUT() != '\n')
+ PUTCHR('\n');
+ if (prv)
+#else
+ if (st & EOF2NL)
+ {
+ st &= ~EOF2NL;
+ *(ip - 1) = c = '\n';
+ }
+ else if (!(st & (FILEPOP|PASSEOF)) && prv)
+#endif
+ {
+ if (!(cur->flags & IN_newline))
+ {
+ cur->flags |= IN_newline;
+ if ((pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC && LASTCHR() != '\f' && LASTCHR() != CC_sub)
+ error(1, "file does not end with %s", pptokchr('\n'));
+ *(ip - 1) = c = '\n';
+ }
+ else
+ {
+ if (!(cur->flags & (IN_noguard|IN_tokens)) && cur->symbol)
+ ppmultiple(ppsetfile(error_info.file), cur->symbol);
+ if (cur->fd >= 0)
+ close(cur->fd);
+ if (pp.incref && !(pp.mode & INIT))
+ {
+ SYNCOUT();
+ (*pp.incref)(error_info.file, cur->file, error_info.line - 1, PP_SYNC_POP);
+ CACHEOUT();
+ }
+ goto fsm_pop;
+ }
+ }
+ else
+ c = EOF;
+ }
+ break;
+ case IN_MACRO:
+ case IN_MULTILINE:
+#if !CPP
+ if (!(st & PASSEOF))
+#endif
+#if COMPATIBLE
+ if (prv && (!INMACRO(rp) || (st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && ppismac(*prv->nextchr)))
+#else
+ if (prv && !INMACRO(rp))
+#endif
+ {
+ if (cur->type == IN_MULTILINE)
+ {
+ while (pp.control-- != cur->control)
+ error(2, "#%s on line %d has no #%s", dirname(IF), GETIFLINE(pp.control+1), dirname(ENDIF));
+ free(cur->buffer);
+ error_info.file = cur->file;
+ error_info.line = cur->line;
+ if (pp.linesync)
+ {
+ SYNCOUT();
+ (*pp.linesync)(error_info.line, error_info.file);
+ CACHEOUT();
+ }
+ }
+ cur->symbol->flags &= ~SYM_DISABLED;
+ if (cur->symbol->flags & SYM_FUNCTION)
+ popframe(pp.macp);
+ POP();
+#if CPP
+ if (!(st & COMPATIBILITY) && ppisidig(*(op - 1)) && ppisidig(*ip)) UNGETCHR(' ');
+#endif
+ bp = ip;
+ goto fsm_get;
+ }
+ c = EOF;
+ break;
+ case IN_QUOTE:
+ if (prv)
+ {
+ error_info.line = cur->line;
+ st &= ~(ESCAPE|QUOTE);
+ POP();
+ c = '"';
+ }
+ else c = EOF;
+ break;
+ case IN_SQUOTE:
+ if (prv)
+ {
+ error_info.line = cur->line;
+ st &= ~(ESCAPE|SQUOTE);
+ POP();
+ c = '\'';
+ }
+ else c = EOF;
+ break;
+ case IN_STRING:
+#if CPP
+ if (prv)
+#else
+ if (!(st & PASSEOF) && !(cur->flags & IN_expand) && prv)
+#endif
+ {
+ if (cur->flags & IN_disable) st |= DISABLE;
+ else st &= ~DISABLE;
+ POP();
+ bp = ip;
+ goto fsm_get;
+ }
+ c = EOF;
+ break;
+ default:
+ c = EOF;
+ break;
+ }
+ }
+ bp = ip - 1;
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+
+#if !CPP
+ case S_HUH:
+ if (INOPSPACE(rp))
+ {
+ if (c == '=')
+ {
+#if PROTOTYPE
+ if (pp.in->flags & IN_prototype) PUTCHR(c);
+ else
+ {
+#endif
+ while (*(op - 1) == ' ' || *(op - 1) == '\t') op--;
+ PUTCHR(c);
+ if (st & (STRICT|WARN)) error(1, "%-*.*s: space ignored in operator", op - tp, op - tp, tp);
+#if PROTOTYPE
+ }
+#endif
+ switch (*tp)
+ {
+ case '/':
+ c = T_DIVEQ;
+ break;
+ case '%':
+ c = T_MODEQ;
+ break;
+ case '&':
+ c = T_ANDEQ;
+ break;
+ case '*':
+ c = T_MPYEQ;
+ break;
+ case '+':
+ c = T_ADDEQ;
+ break;
+ case '-':
+ c = T_SUBEQ;
+ break;
+ case '^':
+ c = T_XOREQ;
+ break;
+ case '|':
+ c = T_OREQ;
+ break;
+ case '<':
+ c = T_LSHIFTEQ;
+ break;
+ case '>':
+ c = T_RSHIFTEQ;
+ break;
+ }
+ }
+ else
+ {
+ BACKIN();
+ switch (c = *tp)
+ {
+ case '<':
+ c = T_LSHIFT;
+ break;
+ case '>':
+ c = T_RSHIFT;
+ break;
+ }
+ }
+ }
+ else if (pp.level > 1 || (pp.option & PRESERVE)) PUTCHR(c);
+ else if (tp == op)
+ {
+ if (pp.in->type != IN_BUFFER)
+ {
+ if (!(pp.option & ALLPOSSIBLE))
+ error(1, "%s: invalid character ignored", pptokchr(c));
+ goto fsm_top;
+ }
+ PUTCHR(c);
+ }
+ else if (*tp == ':')
+ {
+ PUTCHR(c);
+ if (c == '=') error(2, "real programmers use =");
+ else c = '+';
+ }
+ else
+ {
+ BACKIN();
+ c = *tp;
+ }
+ break;
+#endif
+
+ case S_QUAL:
+ if ((state = NEXT(state)) != LIT1)
+ {
+ rp = fsm[state];
+ bp = ip;
+#if CPP
+ qual = 1;
+#if COMPATIBLE
+ if (!(st & COMPATIBILITY) || c != 'u' && c != 'U')
+#endif
+ PUTCHR(c);
+#else
+ switch (c)
+ {
+ case 'f':
+ case 'F':
+ qual |= N_FLOAT;
+#if COMPATIBLE
+ if (!(st & COMPATIBILITY))
+#endif
+ PUTCHR(c);
+ break;
+ case 'l':
+ case 'L':
+ qual |= N_LONG;
+ PUTCHR(c);
+ break;
+ case 'u':
+ case 'U':
+ qual |= N_UNSIGNED;
+#if COMPATIBLE
+ if (!(st & COMPATIBILITY))
+#endif
+ PUTCHR(c);
+ break;
+ default:
+ PUTCHR(c);
+ break;
+ }
+#endif
+ goto fsm_get;
+ }
+#if !CPP
+ qual |= N_WIDE;
+ if (DOSTRIP()) BACKOUT();
+#endif
+ /*FALLTHROUGH*/
+
+ case S_LITBEG:
+#if CPP
+ quot = c;
+ rp = fsm[LIT1];
+ if (op == tp)
+ {
+ PPSYNCLINE();
+ tp = op;
+ }
+#else
+ if ((quot = c) == '<')
+ {
+ if (!(st & HEADER) || (pp.option & (HEADEREXPAND|HEADEREXPANDALL)) && pp.in->type != IN_FILE && pp.in->type != IN_BUFFER && pp.in->type != IN_INIT && pp.in->type != IN_RESCAN)
+ {
+ PUTCHR(c);
+ bp = ip;
+ rp = fsm[LT1];
+ goto fsm_get;
+ }
+ quot = '>';
+ rp = fsm[HDR1];
+ }
+ else rp = fsm[LIT1];
+ if (!DOSTRIP())
+#endif
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+
+ case S_LITEND:
+ n = 1;
+ if (c != quot)
+ {
+ if (c != '\n' && c != EOF)
+ {
+ if (st & (QUOTE|SQUOTE))
+ {
+ if (!(st & ESCAPE))
+ {
+ st |= ESCAPE;
+ quotquot = c;
+ }
+ else if (c == quotquot) st &= ~ESCAPE;
+ }
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+ }
+#if CPP
+ if (st & PASSTHROUGH)
+ {
+ if (c == '\n') goto fsm_newline;
+ bp = ip;
+ goto fsm_start;
+ }
+#endif
+ m = (st & SKIPCONTROL) && (pp.mode & HOSTED) ? -1 : 1;
+ if (c == '\n' && quot == '\'' && (pp.option & STRINGSPAN)) n = 0;
+ else
+#if COMPATIBLE && !CPP
+ if ((st & (COMPATIBILITY|DEFINITION)) != (COMPATIBILITY|DEFINITION))
+#endif
+ {
+ switch (quot)
+ {
+ case '"':
+ if (c == '\n')
+ {
+ if (!(pp.option & STRINGSPAN) || (st & (COMPATIBILITY|STRICT)) == STRICT)
+ error(m, "%s in string", pptokchr(c));
+ error_info.line++;
+ if (!(pp.option & STRINGSPAN))
+ {
+ PUTCHR('\\');
+ c = 'n';
+ }
+ else if (pp.option & STRINGSPLIT)
+ {
+ PUTCHR('\\');
+ PUTCHR('n');
+ PUTCHR('"');
+ PUTCHR('\n');
+ c = '"';
+ }
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+ }
+ error(m, "%s in string", pptokchr(c));
+ c = '\n';
+ break;
+ case '\'':
+ if (!(st & DIRECTIVE) || !(pp.mode & (HOSTED|RELAX)))
+ error(m, "%s in character constant", pptokchr(c));
+ break;
+ case '>':
+ error(m, "%s in header constant", pptokchr(c));
+ break;
+ default:
+ error(m, "%s in %c quote", pptokchr(c), quot);
+ break;
+ }
+#if !CPP
+ if (!DOSTRIP())
+#endif
+ PUTCHR(quot);
+ }
+ if (c == '\n')
+ {
+ UNGETCHR(c);
+ c = quot;
+ }
+ }
+ else if (st & (SQUOTE|QUOTE))
+ {
+ if (!(st & ESCAPE))
+ {
+ st |= ESCAPE;
+ quotquot = c;
+ }
+ else if (c == quotquot) st &= ~ESCAPE;
+ PUTCHR('\\');
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+ }
+#if CPP
+ else PUTCHR(c);
+#else
+ else if (!DOSTRIP()) PUTCHR(c);
+#endif
+#if CATSTRINGS
+#if CPP
+ if (c == '"' && !(st & (COLLECTING|NOTEXT|PASSTHROUGH|SKIPCONTROL)) && (pp.mode & CATLITERAL))
+#else
+ if (c == '"' && pp.level == 1 && !(st & (COLLECTING|JOINING|NOTEXT|SKIPCONTROL)) && (pp.mode & CATLITERAL))
+#endif
+ {
+ char* pptoken;
+ long ppstate;
+
+ pptoken = pp.token;
+ pp.token = pp.catbuf;
+ *pp.token++ = 0;
+ ppstate = (st & STRIP);
+ if (DOSTRIP())
+ ppstate |= ADD|QUOTE;
+ st |= JOINING;
+ st &= ~(NEWLINE|STRIP);
+
+ /*
+ * revert to the top level since string
+ * concatenation crosses file boundaries
+ * (allowing intervening directives)
+ */
+
+ pp.level = 0;
+ SYNCIN();
+ m = n = 0;
+ for (;;)
+ {
+ switch (c = pplex())
+ {
+ case '\n':
+ m++;
+ continue;
+ case ' ':
+ *pp.catbuf = ' ';
+ continue;
+ case T_WSTRING:
+#if !CPP
+ qual = N_WIDE;
+#endif
+ if (ppstate & ADD)
+ ppstate &= ~ADD;
+ else if (m == n || !(st & SPACEOUT))
+ op--;
+ else
+ {
+ n = m;
+ *(op - 1) = '\\';
+ *op++ = '\n';
+ }
+ STRCOPY(op, pp.token + 2 + (*pp.token == ' '), s);
+ continue;
+ case T_STRING:
+ if (ppstate & ADD)
+ ppstate &= ~ADD;
+ else if (m == n || !(st & SPACEOUT))
+ op--;
+ else
+ {
+ n = m;
+ *(op - 1) = '\\';
+ *op++ = '\n';
+ }
+ STRCOPY(op, pp.token + 1 + (*pp.token == ' '), s);
+ continue;
+ case 0:
+ m = error_info.line ? (error_info.line - 1) : 0;
+ *pp.token = 0;
+ /*FALLTHROUGH*/
+ default:
+ if (m)
+ {
+ if (--m)
+ {
+ pp.state |= HIDDEN|SYNCLINE;
+ pp.hidden += m;
+ }
+#if COMPATIBLE
+ if ((st & COMPATIBILITY) && c == '#' && *(pp.token - 1))
+ {
+ *(pp.token + 3) = *(pp.token + 2);
+ *(pp.token + 2) = *(pp.token + 1);
+ *(pp.token + 1) = *pp.token;
+ *pp.token = *(pp.token - 1);
+ }
+ error_info.line--;
+ *--pp.token = '\n';
+#endif
+ }
+ else if (*(pp.token - 1))
+ pp.token--;
+ if (ppisidig(*pp.token))
+ *op++ = ' ';
+ if (pp.in->type == IN_MACRO && (s = strchr(pp.token, MARK)) && !*(s + 1))
+ {
+ *(s + 1) = MARK;
+ *(s + 2) = 0;
+ }
+ PUSH_STRING(pp.token);
+ pp.state &= ~(JOINING|NEWLINE);
+ pp.state |= ppstate & ~(ADD|QUOTE);
+ if ((ppstate & (ADD|QUOTE)) == QUOTE)
+ op--;
+ break;
+ }
+ break;
+ }
+ pp.token = pptoken;
+ CACHEIN();
+ pp.level = 1;
+#if !CPP
+ c = T_STRING | qual;
+ break;
+#endif
+ }
+#endif
+#if CPP
+ if (n && !(st & (PASSTHROUGH|SKIPCONTROL|NOTEXT)) && c == '\'' && (op - tp) <= 2 && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "empty character constant");
+ st &= ~(ESCAPE|NEWLINE);
+ pp.in->flags |= IN_tokens;
+ count(token);
+ goto fsm_start;
+#else
+ st &= ~ESCAPE;
+ switch (quot)
+ {
+ case '\'':
+ if (n && !(st & NOTEXT) && (op - tp) <= (DOSTRIP() ? 0 : 2) && !(pp.mode & (HOSTED|RELAX)))
+ error(1, "empty character constant");
+ c = T_CHARCONST | qual;
+ break;
+ case '>':
+ c = T_HEADER;
+ break;
+ default:
+ if (c == quot)
+ c = T_STRING | qual;
+ break;
+ }
+ break;
+#endif
+
+ case S_LITESC:
+ if (st & (COLLECTING|DIRECTIVE|QUOTE|SQUOTE))
+ {
+ if (st & ESCAPE)
+ {
+ PUTCHR('\\');
+ if (c == quot) PUTCHR('\\');
+ }
+ PUTCHR(c);
+ }
+#if CPP
+ else if (st & PASSTHROUGH) PUTCHR(c);
+#endif
+ else if (pp.option & PRESERVE) PUTCHR(c);
+ else switch (c)
+ {
+ case 'b':
+ case 'f':
+ case 'n':
+ case 'r':
+ case 't':
+ case '\\':
+ case '\'':
+ case '"':
+ case '?':
+ PUTCHR(c);
+ break;
+#if COMPATIBLE
+ case '8':
+ case '9':
+ if (!(st & COMPATIBILITY)) goto unknown;
+ if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
+ /*FALLTHROUGH*/
+#endif
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ n = c - '0';
+ for (m = 0; m < 2; m++)
+ {
+ GET(c, c, tp, xp);
+ switch (c)
+ {
+#if COMPATIBLE
+ case '8':
+ case '9':
+ if (!(st & COMPATIBILITY))
+ {
+ UNGETCHR(c);
+ break;
+ }
+ if (st & STRICT) error(1, "%c: invalid character in octal character escape", c);
+ /*FALLTHROUGH*/
+#endif
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ n = (n << 3) + c - '0';
+ continue;
+ default:
+ UNGETCHR(c);
+ break;
+ }
+ break;
+ }
+ if (n & ~0777) error(1, "octal character constant too large");
+ goto octal;
+ case 'a':
+ if (pp.option & MODERN)
+ {
+ PUTCHR(c);
+ break;
+ }
+#if COMPATIBLE
+ if (st & COMPATIBILITY) goto unknown;
+#endif
+ n = CC_bel;
+ goto octal;
+ case 'v':
+ if (pp.option & MODERN)
+ {
+ PUTCHR(c);
+ break;
+ }
+ n = CC_vt;
+ goto octal;
+ case 'E':
+ if (st & (COMPATIBILITY|STRICT)) goto unknown;
+ n = CC_esc;
+ goto octal;
+ case 'x':
+#if COMPATIBLE
+ if (st & COMPATIBILITY) goto unknown;
+#endif
+ n = 0;
+ for (m = 0; m < 3; m++)
+ {
+ GET(c, c, tp, xp);
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ n = (n << 4) + c - '0';
+ continue;
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ n = (n << 4) + c - 'a' + 10;
+ continue;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ n = (n << 4) + c - 'A' + 10;
+ continue;
+ default:
+ if (!m) error(1, "\\x%c: invalid character in hexadecimal character constant", c);
+ UNGETCHR(c);
+ break;
+ }
+ break;
+ }
+ if (n & ~0777) error(1, "hexadecimal character constant too large");
+ octal:
+ PUTCHR(((n >> 6) & 07) + '0');
+ PUTCHR(((n >> 3) & 07) + '0');
+ PUTCHR((n & 07) + '0');
+ break;
+ default:
+ unknown:
+ if (st & (STRICT|WARN)) error(1, "\\%c: non-standard character constant", c);
+ PUTCHR(c);
+ break;
+ }
+ state = LIT1;
+ goto fsm_begin;
+
+ case S_MACRO:
+ BACKIN();
+#if CPP
+ if (st & (DISABLE|SKIPCONTROL|SKIPMACRO))
+ {
+ if (st & SKIPMACRO)
+ pp.mode |= MARKMACRO;
+ st &= ~(NEWLINE|SKIPMACRO);
+ pp.in->flags |= IN_tokens;
+ count(token);
+ goto fsm_start;
+ }
+ count(candidate);
+ SETCHR(0);
+ switch (state = INDEX(rp))
+ {
+ case HIT0:
+ tp = op - 1;
+ break;
+ case HITN:
+ bp = tp;
+ tp = op - ((pp.truncate && pp.truncate < (HITN - HIT0)) ? (pp.truncate - 1) : (HITN - HIT0));
+ while (tp > bp && ppisidig(*(tp - 1))) tp--;
+ break;
+ default:
+ bp = tp;
+ if ((tp = op - (state - HIT0)) > bp && *(tp - 1) == 'L') tp--;
+ break;
+ }
+ if (sym = ppsymref(pp.symtab, tp))
+ {
+ SYNCIN();
+ n = ppcall(sym, 0);
+ CACHEIN();
+ if (n >= 0)
+ {
+ BACKOUT();
+ if (!n)
+ {
+ if (sp) op = sp;
+ else
+ {
+ s = ip;
+ ip = sym->macro->value;
+ c = sym->macro->size;
+ while (c > 0)
+ {
+ if (op + c < xp + PPBUFSIZ) n = c;
+ else n = xp + PPBUFSIZ - op;
+ MEMCPY(op, ip, n);
+ c -= n;
+ PPCHECKOUT();
+ }
+ ip = s;
+ }
+ }
+ else if ((sym->flags & SYM_MULTILINE) && pp.linesync)
+ {
+ SYNCOUT();
+ if (!(state & NEWLINE))
+ ppputchar('\n');
+ (*pp.linesync)(error_info.line, error_info.file);
+ CACHEOUT();
+ }
+ }
+ }
+ pp.in->flags |= IN_tokens;
+ goto fsm_start;
+#else
+ if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL|SKIPMACRO))
+ {
+ if (st & SKIPMACRO)
+ pp.mode |= MARKMACRO;
+ st &= ~(NEWLINE|NOEXPAND|SKIPMACRO);
+ c = T_ID;
+ if (pp.level == 1)
+ {
+ pp.in->flags |= IN_tokens;
+ if (st & NOTEXT)
+ {
+ BACKOUT();
+ goto fsm_top;
+ }
+ if (st & COMPILE)
+ {
+ SETCHR(0);
+ if (pp.truncate && (op - tp) > pp.truncate) tp[pp.truncate] = 0;
+ sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp);
+ fsm_noise:
+ if (pp.symbol = sym)
+ {
+ if ((sym->flags & SYM_KEYWORD) && (!pp.truncate || (op - tp) <= pp.truncate || (tp[pp.truncate] = '_', tp[pp.truncate + 1] = 0, pp.symbol = sym = (pp.option & NOHASH) ? ppsymref(pp.symtab, tp) : ppsymset(pp.symtab, tp), 0)))
+ {
+ c = ((struct ppsymkey*)sym)->lex;
+ /*UNDENT*/
+
+#define ADVANCE() do{if(pp.toknxt<op)pp.token=pp.toknxt;}while(0)
+
+#define NOISE_BRACE 01
+#define NOISE_NOSPACEOUT 02
+#define NOISE_PAREN 04
+
+ if ((pp.option & NOISE) && ppisnoise(c))
+ {
+ if (c != T_NOISE)
+ {
+ int p;
+ int f;
+ char* pptoken;
+ PPCOMMENT ppcomment;
+
+ SYNCIN();
+ pp.toknxt = op;
+ f = 0;
+ if (!(pp.state & SPACEOUT))
+ {
+ pp.state |= SPACEOUT;
+ f |= NOISE_NOSPACEOUT;
+ }
+ ppcomment = pp.comment;
+ pp.comment = 0;
+ op = (pptoken = tp) + MAXTOKEN;
+ switch (c)
+ {
+ case T_X_GROUP:
+ m = p = 0;
+ quot = 1;
+ for (;;)
+ {
+ ADVANCE();
+ switch (c = pplex())
+ {
+ case '(':
+ case '{':
+ if (!p)
+ {
+ if (c == '(')
+ {
+ if (f & NOISE_PAREN)
+ {
+ ungetchr(c);
+ *--pp.toknxt = 0;
+ break;
+ }
+ f |= NOISE_PAREN;
+ p = ')';
+ }
+ else
+ {
+ f |= NOISE_BRACE|NOISE_PAREN;
+ p = '}';
+ }
+ n = 1;
+ m = c;
+ }
+ else if (c == m) n++;
+ quot = 0;
+ continue;
+ case ')':
+ case '}':
+ if (c == p && --n <= 0)
+ {
+ if (c == '}') break;
+ m = '\n';
+ p = 0;
+ }
+ quot = 0;
+ continue;
+ case ' ':
+ continue;
+ case '\n':
+ error_info.line++;
+ if (!m) m = '\n';
+ continue;
+ case 0:
+ break;
+ case T_ID:
+ if (quot) continue;
+ /*FALLTHROUGH*/
+ default:
+ if (m == '\n')
+ {
+ /*
+ * NOTE: token expanded again
+ */
+
+ s = pp.toknxt;
+ while (s > pp.token) ungetchr(*--s);
+ *(pp.toknxt = s) = 0;
+ break;
+ }
+ continue;
+ }
+ break;
+ }
+ break;
+ case T_X_LINE:
+ for (;;)
+ {
+ ADVANCE();
+ switch (pplex())
+ {
+ case 0:
+ break;
+ case '\n':
+ error_info.line++;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ break;
+ case T_X_STATEMENT:
+ for (;;)
+ {
+ ADVANCE();
+ switch (pplex())
+ {
+ case 0:
+ break;
+ case ';':
+ ungetchr(';');
+ *(pp.toknxt = pp.token) = 0;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ break;
+ }
+ pp.comment = ppcomment;
+ if (f & NOISE_NOSPACEOUT)
+ pp.state &= ~SPACEOUT;
+ CACHEIN();
+ tp = pptoken;
+ op = pp.toknxt;
+ c = T_NOISES;
+ }
+ if (pp.option & NOISEFILTER)
+ {
+ BACKOUT();
+ goto fsm_top;
+ }
+ }
+
+ /*INDENT*/
+ }
+ else if ((pp.option & NOISE) && c == T_ID && strneq(tp, "__builtin_", 10))
+ {
+ hashlook(pp.symtab, tp, HASH_DELETE, NiL);
+ pp.symbol = sym = (struct ppsymbol*)ppkeyset(pp.symtab, tp);
+ sym->flags |= SYM_KEYWORD;
+ c = ((struct ppsymkey*)sym)->lex = T_BUILTIN;
+ }
+ }
+ }
+ goto fsm_symbol;
+ }
+ goto fsm_check;
+ }
+ if (pp.level == 1)
+ {
+ st &= ~(NEWLINE|PASSEOF);
+ pp.in->flags |= IN_tokens;
+ }
+ else st &= ~PASSEOF;
+ count(candidate);
+ SETCHR(0);
+ if (sym = ppsymref(pp.symtab, tp))
+ {
+ SYNCIN();
+ c = ppcall(sym, 1);
+ CACHEIN();
+ if (c >= 0)
+ {
+ BACKOUT();
+ if ((sym->flags & SYM_MULTILINE) && pp.linesync)
+ {
+ SYNCOUT();
+ (*pp.linesync)(error_info.line, error_info.file);
+ CACHEOUT();
+ }
+ goto fsm_top;
+ }
+ }
+ c = T_ID;
+ if (pp.level == 1)
+ {
+ if (st & NOTEXT)
+ {
+ BACKOUT();
+ goto fsm_top;
+ }
+ if (st & COMPILE)
+ {
+ if (pp.truncate && (op - tp) > pp.truncate)
+ {
+ tp[pp.truncate] = 0;
+ sym = 0;
+ }
+ if (!sym)
+ {
+ if (!(pp.option & NOHASH)) sym = ppsymset(pp.symtab, tp);
+ else if (!(sym = ppsymref(pp.symtab, tp))) goto fsm_symbol;
+ }
+ goto fsm_noise;
+ }
+ goto fsm_symbol;
+ }
+ goto fsm_check;
+#endif
+
+ case S_SHARP:
+ if (c == '(')
+ {
+ pp.in->flags |= IN_tokens;
+ if ((st & STRICT) && pp.in->type != IN_MACRO && pp.in->type != IN_MULTILINE)
+ {
+ if (!(pp.mode & HOSTED)) error(1, "non-standard reference to #(...)");
+ if (st & STRICT)
+ {
+ PUTCHR(c);
+#if CPP
+ st &= ~NEWLINE;
+ count(token);
+ goto fsm_start;
+#else
+ break;
+#endif
+ }
+ }
+ if (st & (COLLECTING|DEFINITION|DISABLE|SKIPCONTROL))
+ {
+ PUTCHR(c);
+#if CPP
+ st &= ~NEWLINE;
+ count(token);
+ goto fsm_start;
+#else
+ st &= ~NOEXPAND;
+ break;
+#endif
+ }
+ op--;
+ SYNC();
+ ppbuiltin();
+ CACHE();
+#if CPP
+ count(token);
+ goto fsm_start;
+#else
+ goto fsm_top;
+#endif
+ }
+ BACKIN();
+#if CPP
+ if (!(st & NEWLINE) || !(pp.in->type & IN_TOP))
+ {
+ fsm_nondirective:
+ st &= ~NEWLINE;
+ pp.in->flags |= IN_tokens;
+ count(token);
+ goto fsm_start;
+ }
+ if (*(s = tp) != '#')
+ {
+#if COMPATIBLE
+ if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) goto fsm_nondirective;
+#endif
+ while (*s == ' ' || *s == '\t') s++;
+ if (*s != '#') goto fsm_nondirective;
+ }
+ BACKOUT();
+#else
+ if (!(st & NEWLINE) || (st & DEFINITION) || !(pp.in->type & IN_TOP))
+ {
+ if (c == '#')
+ {
+ SKIPIN();
+ if (!(st & DEFINITION))
+ PUTCHR(c);
+ c = T_TOKCAT;
+ }
+ else if (pp.level == 1 && !(st & (JOINING|SPACEOUT)) && !(pp.option & PRESERVE))
+ {
+ char* pptoken;
+ char* oop;
+ PPCOMMENT ppcomment;
+
+ SYNCIN();
+ pp.toknxt = oop = op;
+ pp.state |= SPACEOUT;
+ ppcomment = pp.comment;
+ pp.comment = 0;
+ op = (pptoken = tp) + MAXTOKEN;
+ for (;;)
+ {
+ ADVANCE();
+ switch (pplex())
+ {
+ case 0:
+ break;
+ case '\n':
+ error_info.line++;
+ break;
+ default:
+ continue;
+ }
+ break;
+ }
+ pp.comment = ppcomment;
+ pp.state &= ~SPACEOUT;
+ CACHEIN();
+ tp = pptoken;
+ *--op = 0;
+ op = oop;
+ if (pp.pragma && !(st & NOTEXT))
+ {
+ *s = 0;
+ SYNC();
+ (*pp.pragma)(NiL, NiL, NiL, tp, 1);
+ CACHE();
+ }
+ if (!c) BACKIN();
+ goto fsm_top;
+ }
+ else c = '#';
+ break;
+ }
+ if ((st & (COLLECTING|STRICT)) == (COLLECTING|STRICT))
+ error(1, "directives in macro call arguments are not portable");
+#endif
+ if (c == '#' && pp.in->type == IN_RESCAN)
+ {
+ /*
+ * pass line to pp.pragma VERBATIM
+ */
+
+ SKIPIN();
+ s = pp.valbuf;
+ while ((c = GETCHR()) && c != '\n')
+ if ((*s++ = c) == MARK) SKIPIN();
+ if (pp.pragma && !(st & NOTEXT))
+ {
+ *s = 0;
+ SYNC();
+ (*pp.pragma)(NiL, NiL, NiL, pp.valbuf, 1);
+ CACHE();
+ }
+ if (!c) BACKIN();
+#if CPP
+ goto fsm_start;
+#else
+ goto fsm_top;
+#endif
+ }
+ SYNC();
+ ppcontrol();
+ CACHE();
+#if CPP
+ if (st & (NOTEXT|SKIPCONTROL))
+ {
+ if (!sp)
+ {
+ PPCHECKOUTTP();
+ sp = tp;
+ }
+ }
+ else if (sp)
+ {
+ tp = op = sp;
+ sp = 0;
+ }
+ goto fsm_start;
+#else
+ goto fsm_top;
+#endif
+
+ case S_NL:
+#if CPP
+ if (op == tp && !(st & JOINING) && pp.in->type == IN_FILE)
+ {
+ st |= NEWLINE|HIDDEN;
+ pp.hidden++;
+ error_info.line++;
+ goto fsm_start;
+ }
+#endif
+ fsm_newline:
+#if CPP
+ if (sp)
+ op = sp;
+ else if (!(pp.in->flags & IN_noguard))
+ {
+ while (tp < op)
+ if ((c = *tp++) != ' ' && c != '\t')
+ {
+ pp.in->flags |= IN_tokens;
+ break;
+ }
+ c = '\n';
+ }
+ st |= NEWLINE;
+ error_info.line++;
+ if (*ip == '\n' && *(ip + 1) != '\n' && !pp.macref && !(st & (ADD|HIDDEN)))
+ {
+ ip++;
+ PUTCHR('\n');
+ error_info.line++;
+ }
+ if ((st & NOTEXT) && ((pp.mode & FILEDEPS) || (pp.option & (DEFINITIONS|PREDEFINITIONS))))
+ BACKOUT();
+ else
+ {
+ debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
+ PUTCHR('\n');
+ PPSYNCLINE();
+ if (sp)
+ {
+ PPCHECKOUT();
+ sp = op;
+ }
+ }
+ goto fsm_start;
+#else
+ st |= NEWLINE;
+ if (pp.level == 1)
+ {
+ error_info.line++;
+ if (!(st & (JOINING|SPACEOUT)))
+ {
+ debug((-5, "token[%d] %03o = %s [line=%d]", pp.level, c, pptokchr(c), error_info.line));
+ BACKOUT();
+ goto fsm_top;
+ }
+ }
+ BACKOUT();
+ if (st & SKIPCONTROL)
+ {
+ error_info.line++;
+ st |= HIDDEN;
+ pp.hidden++;
+ goto fsm_start;
+ }
+ PUTCHR(c = '\n');
+ goto fsm_return;
+#endif
+
+#if !CPP
+ case S_TOK:
+ PUTCHR(c);
+ c = TYPE(state) | qual;
+ break;
+
+ case S_TOKB:
+ BACKIN();
+ c = TYPE(state) | qual;
+ break;
+#endif
+
+ case S_VS:
+ PUTCHR(c);
+#if !CPP
+ if (st & NOVERTICAL)
+ {
+ error(1, "%s invalid in directives", pptokchr(c));
+ st &= ~NOVERTICAL;
+ }
+#endif
+#if COMPATIBLE
+ if (st & COMPATIBILITY) st |= NEWLINE;
+#endif
+#if CPP
+ if (!(pp.in->flags & IN_noguard))
+ while (tp < op)
+ if ((c = *tp++) != ' ' && c != '\t')
+ {
+ pp.in->flags |= IN_tokens;
+ break;
+ }
+ goto fsm_start;
+#else
+ bp = ip;
+ rp = fsm[WS1];
+ goto fsm_get;
+#endif
+
+#if !CPP
+ case S_WS:
+#if COMPATIBLE
+ if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) st &= ~NEWLINE;
+#endif
+ if (pp.level == 1)
+ {
+ if ((st & (COMPATIBILITY|SPACEOUT)) && !(st & TRANSITION))
+ {
+ if (st & (COMPILE|NOTEXT))
+ {
+#if CATSTRINGS
+ if ((st & (JOINING|NOTEXT|SPACEOUT)) != SPACEOUT)
+#else
+ if ((st & (NOTEXT|SPACEOUT)) != SPACEOUT)
+#endif
+ {
+ BACKOUT();
+ bp = ip - 1;
+ rp = fsm[START];
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+ }
+ }
+ else
+#if CATSTRINGS
+ if (!(st & JOINING))
+#endif
+ {
+ tp = op;
+ bp = ip - 1;
+ rp = fsm[START];
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+ }
+ BACKIN();
+ c = ' ';
+ goto fsm_return;
+ }
+ BACKOUT();
+ bp = ip - 1;
+ rp = fsm[START];
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+ }
+ if (st & (NOSPACE|SKIPCONTROL))
+ {
+ BACKOUT();
+ bp = ip - 1;
+ rp = fsm[START];
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+ }
+ if (c != '\n')
+ {
+ BACKIN();
+ c = ' ';
+ }
+ if (!(pp.option & PRESERVE))
+ {
+ BACKOUT();
+ PUTCHR(c);
+ }
+ goto fsm_return;
+#endif
+
+ default:
+ if (state & SPLICE)
+ {
+ switch (c)
+ {
+ case MARK:
+ /*
+ * internal mark
+ */
+
+ switch (pp.in->type)
+ {
+ case IN_BUFFER:
+ case IN_FILE:
+#if !CPP
+ case IN_INIT:
+#if CATSTRINGS
+ if ((st & JOINING) && (!INQUOTE(rp) || quot != '"') || pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
+#else
+ if (pp.level > 1 && (rp == fsm[START] || INQUOTE(rp)))
+#endif
+ PUTCHR(c);
+#endif
+ break;
+ default:
+ switch (GETCHR())
+ {
+ case 'A':
+ if (!(st & (DEFINITION|DISABLE)))
+ {
+ c = GETCHR();
+ SYNCIN();
+ if (pp.macp->arg[c - ARGOFFSET][-1])
+ PUSH_EXPAND(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
+ else
+ PUSH_COPY(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
+ CACHEIN();
+ bp = ip;
+ goto fsm_get;
+ }
+ /*FALLTHROUGH*/
+ case 'C':
+ c = GETCHR() - ARGOFFSET;
+ if (!*(s = pp.macp->arg[c]) && (pp.in->symbol->flags & SYM_VARIADIC) && pp.in->symbol->macro->arity == (c + 1))
+ {
+ s = ip - 3;
+ while (--op > tp && --s > bp && ppisidig(*s));
+ }
+ else
+ {
+ SYNCIN();
+ PUSH_COPY(s, pp.macp->line);
+ CACHEIN();
+ }
+ bp = ip;
+ goto fsm_get;
+ case 'F':
+ error_info.file = (char*)strtoul(ip, &s, 16);
+ debug((-6, "actual sync: file = \"%s\"", error_info.file));
+ bp = ip = s + 1;
+ goto fsm_get;
+ case 'L':
+ error_info.line = strtoul(ip, &s, 16);
+ debug((-6, "actual sync: line = %d", error_info.line));
+ bp = ip = s + 1;
+ goto fsm_get;
+ case 'Q':
+ c = GETCHR();
+ SYNCIN();
+ PUSH_QUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
+ CACHEIN();
+ bp = ip - 1;
+ if (st & (COLLECTING|EOF2NL|JOINING)) rp = fsm[START];
+ if (state = rp[c = '"']) goto fsm_next;
+ goto fsm_get;
+ case 'S':
+ c = GETCHR();
+ SYNCIN();
+ PUSH_SQUOTE(pp.macp->arg[c - ARGOFFSET], pp.macp->line);
+ CACHEIN();
+ bp = ip - 1;
+ if (st & COLLECTING) rp = fsm[START];
+ if (state = rp[c = '\'']) goto fsm_next;
+ goto fsm_get;
+ case 'X':
+ if (pp.in->type != IN_COPY)
+ st |= SKIPMACRO;
+ if (pp.level <= 1)
+ {
+ bp = ip;
+ goto fsm_get;
+ }
+ if (pp.in->type == IN_EXPAND)
+ {
+ st &= ~SKIPMACRO;
+ PUTCHR(c);
+ PUTCHR('X');
+ }
+ c = GETCHR();
+ break;
+ case 0:
+ if ((state &= ~SPLICE) >= TERMINAL) goto fsm_terminal;
+ goto fsm_begin;
+ default:
+#if DEBUG
+ error(PANIC, "invalid mark op `%c'", LASTCHR());
+ /*FALLTHROUGH*/
+ case MARK:
+#endif
+#if CATSTRINGS
+ if ((st & (JOINING|QUOTE)) == JOINING)
+ {
+ if (!INQUOTE(rp))
+ PUTCHR(c);
+ }
+ else
+#endif
+#if CPP
+ if (rp != fsm[START] && !INQUOTE(rp))
+ UNGETCHR(c);
+#else
+ if (rp != fsm[START] && !INQUOTE(rp))
+ UNGETCHR(c);
+ else if (pp.level > 1)
+ PUTCHR(c);
+#endif
+ break;
+ }
+ break;
+ }
+ break;
+ case '?':
+ /*
+ * trigraph
+ */
+
+ if (pp.in->type == IN_FILE)
+ {
+ GET(c, n, tp, xp);
+ if (n == '?')
+ {
+ GET(c, n, tp, xp);
+ if (c = trigraph[n])
+ {
+ if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
+ error(1, "trigraph conversion %c%c%c -> %c%s", '?', '?', n, c, (st & TRANSITION) ? "" : " inhibited");
+#if COMPATIBLE
+ if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
+ {
+#endif
+ *(bp = ip - 1) = c;
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+#if COMPATIBLE
+ }
+#endif
+ }
+ if (n != EOB) BACKIN();
+ UNGETCHR(c = '?');
+ }
+ else if (n != EOB) BACKIN();
+ }
+ break;
+ case '%':
+ case '<':
+ case ':':
+ /*
+ * digraph = --trigraph
+ */
+
+ if (pp.in->type == IN_FILE && (pp.option & PLUSPLUS))
+ {
+ m = 0;
+ GET(c, n, tp, xp);
+ switch (n)
+ {
+ case '%':
+ if (c == '<') m = '{';
+ break;
+ case '>':
+ if (c == '%') m = '}';
+ else if (c == ':') m = ']';
+ break;
+ case ':':
+ if (c == '%') m = '#';
+ else if (c == '<') m = '[';
+ break;
+ }
+ if (m)
+ {
+ if ((st & WARN) && (st & (COMPATIBILITY|TRANSITION)) && !(pp.mode & HOSTED) && !INCOMMENT(rp))
+ error(1, "digraph conversion %c%c -> %c%s", c, n, m, (st & TRANSITION) ? "" : " inhibited");
+#if COMPATIBLE
+ if ((st & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY)
+ {
+#endif
+ *(bp = ip - 1) = c = m;
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+#if COMPATIBLE
+ }
+#endif
+ }
+ if (n != EOB) BACKIN();
+ }
+ break;
+ case '\\':
+ /*
+ * line splice
+ */
+
+ if (pp.in->type == IN_FILE && (!(pp.option & PLUSSPLICE) || !INCOMMENTXX(rp)))
+ {
+ m = 0;
+ GET(c, n, tp, xp);
+ if ((pp.option & SPLICESPACE) && !INQUOTE(rp))
+ while (n == ' ')
+ {
+ GET(c, n, tp, xp);
+ m = 1;
+ }
+ if (n == '\r')
+ {
+ GET(c, n, tp, xp);
+ if (n != '\n' && n != EOB)
+ BACKIN();
+ }
+ if (n == '\n')
+ {
+#if CPP
+ if (INQUOTE(rp))
+ {
+ if ((pp.option & STRINGSPLIT) && quot == '"')
+ {
+ PUTCHR(quot);
+ PUTCHR(n);
+ PUTCHR(quot);
+ }
+ else if (*pp.lineid)
+ {
+ PUTCHR(c);
+ PUTCHR(n);
+ }
+ else
+ {
+ st |= HIDDEN;
+ pp.hidden++;
+ }
+ }
+ else
+#else
+#if COMPATIBLE
+ if (!INQUOTE(rp) && (st & (COMPATIBILITY|DEFINITION|TRANSITION)) == (COMPATIBILITY|DEFINITION))
+ {
+ if (op == tp)
+ {
+ st |= HIDDEN;
+ pp.hidden++;
+ error_info.line++;
+ if (st & SPACEOUT)
+ goto fsm_start;
+ c = (pp.option & SPLICECAT) ? '\t' : ' ';
+ PUTCHR(c);
+ goto fsm_check;
+ }
+ UNGETCHR(n);
+ state &= ~SPLICE;
+ goto fsm_terminal;
+ }
+#endif
+#endif
+ {
+ st |= HIDDEN;
+ pp.hidden++;
+ }
+#if CPP
+ spliced++;
+#else
+ error_info.line++;
+#endif
+ bp = ip;
+ goto fsm_get;
+ }
+ else if ((n == 'u' || n == 'U') && !INQUOTE(rp))
+ {
+ PUTCHR(c);
+ PUTCHR(n);
+ bp = ip;
+ goto fsm_get;
+ }
+#if COMPATIBLE
+ else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && (n == '"' || n == '\'') && !INQUOTE(rp))
+ {
+ PUTCHR(c);
+ PUTCHR(n);
+ bp = ip;
+ goto fsm_get;
+ }
+#endif
+ else if (n != EOB)
+ BACKIN();
+ if (m && INSPACE(rp))
+ UNGETCHR(c);
+ }
+#if COMPATIBLE
+ else if ((st & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY && !INQUOTE(rp))
+ {
+ GET(c, n, tp, xp);
+ if (n == '"' || n == '\'')
+ {
+ PUTCHR(c);
+ PUTCHR(n);
+ bp = ip;
+ goto fsm_get;
+ }
+ if (n != EOB)
+ BACKIN();
+ }
+#endif
+ break;
+ case '\r':
+ /*
+ * barf
+ */
+
+ if (pp.in->type == IN_FILE)
+ {
+ GET(c, n, tp, xp);
+ if (n == '\n')
+ {
+ *(bp = ip - 1) = c = n;
+ if (state = rp[c]) goto fsm_next;
+ goto fsm_get;
+ }
+ if (n != EOB) BACKIN();
+ }
+ break;
+ case CC_sub:
+ /*
+ * barf & puke
+ */
+
+ if ((pp.option & ZEOF) && pp.in->type == IN_FILE)
+ {
+ pp.in->flags |= IN_eof;
+ c = 0;
+ state = S_EOB;
+ goto fsm_terminal;
+ }
+ break;
+ }
+ if ((state &= ~SPLICE) >= TERMINAL)
+ goto fsm_terminal;
+ PUTCHR(c);
+ goto fsm_begin;
+ }
+#if CPP
+ if (INOPSPACE(rp))
+ {
+ BACKIN();
+ goto fsm_start;
+ }
+#endif
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+ }
+#if !CPP
+ fsm_token:
+ st &= ~NEWLINE;
+ if (pp.level == 1)
+ {
+ pp.in->flags |= IN_tokens;
+ if (st & NOTEXT)
+ {
+ BACKOUT();
+ goto fsm_top;
+ }
+ fsm_symbol:
+ count(token);
+ }
+ fsm_check:
+ if (st & SKIPCONTROL)
+ {
+ BACKOUT();
+ goto fsm_start;
+ }
+ fsm_return:
+#if CPP
+ error_info.line += spliced;
+#endif
+ SETCHR(0);
+ debug((-5, "token[%d] %03o = %s", pp.level, c, pptokstr(tp, 0)));
+ SYNC();
+ pp.level--;
+ error_info.indent--;
+ return c;
+#endif
+}
+
+#if CPP && POOL
+
+#include <ls.h>
+#include <wait.h>
+
+/*
+ * output pool status on exit
+ */
+
+static void
+poolstatus(void)
+{
+ error(ERROR_OUTPUT|0, pp.pool.output, "%d", error_info.errors != 0);
+}
+
+/*
+ * loop on < input output >
+ */
+
+static void
+pool(void)
+{
+ char* ifile;
+ char* ofile;
+
+ ppflushout();
+ if (!sfnew(sfstdin, NiL, SF_UNBOUND, pp.pool.input, SF_READ))
+ error(ERROR_SYSTEM|3, "cannot dup pool input");
+
+ /*
+ * kick the -I cache
+ */
+
+ ppsearch(".", T_STRING, SEARCH_EXISTS);
+
+ /*
+ * loop on < input output >
+ */
+
+ pp.pool.input = 0;
+ while (ifile = sfgetr(sfstdin, '\n', 1))
+ {
+ if (!(ofile = strchr(ifile, ' ')))
+ error(3, "%s: pool output file expected", ifile);
+ *ofile++ = 0;
+ waitpid(0, NiL, WNOHANG);
+ switch (fork())
+ {
+ case -1:
+ error(ERROR_SYSTEM|3, "cannot fork pool");
+ case 0:
+ atexit(poolstatus);
+ error_info.errors = 0;
+ error_info.warnings = 0;
+ close(0);
+ if (open(ifile, O_RDONLY))
+ error(ERROR_SYSTEM|3, "%s: cannot read", ifile);
+ close(1);
+ if (open(ofile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
+ error(ERROR_SYSTEM|3, "%s: cannot create", ofile);
+ pp.outfile = ofile;
+ pathcanon(ifile, 0);
+ ifile = ppsetfile(ifile)->name;
+#if CHECKPOINT
+ if (pp.mode & DUMP)
+ {
+ if (!pp.pragma)
+ error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
+ (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
+ }
+#endif
+ PUSH_FILE(ifile, 0);
+ return;
+ }
+ }
+ while (wait(NiL) != -1);
+}
+
+#endif
diff --git a/usr/src/lib/libpp/common/pplib.h b/usr/src/lib/libpp/common/pplib.h
new file mode 100644
index 0000000000..3428b4d55f
--- /dev/null
+++ b/usr/src/lib/libpp/common/pplib.h
@@ -0,0 +1,863 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor library private definitions
+ */
+
+#ifndef _PPLIB_H
+#define _PPLIB_H
+
+/*
+ * the first definitions control optional code -- 0 disables
+ */
+
+#ifndef ARCHIVE
+#define ARCHIVE 1 /* -I can specify header archives */
+#endif
+#ifndef CATSTRINGS
+#define CATSTRINGS 1 /* concatenate adjacent strings */
+#endif
+#ifndef CHECKPOINT
+#define CHECKPOINT 1 /* checkpoint preprocessed files */
+#endif
+#ifndef COMPATIBLE
+#define COMPATIBLE 1 /* enable COMPATIBILITY related code */
+#endif
+#ifndef MACKEYARGS
+#define MACKEYARGS _BLD_DEBUG /* name=value macro formals and actuals */
+#endif
+#ifndef POOL
+#define POOL 1 /* enable loop on input,output,error */
+#endif
+#ifndef PROTOTYPE
+#define PROTOTYPE 1 /* enable ppproto code */
+#endif
+
+#define TRUNCLENGTH 8 /* default TRUNCATE length */
+
+#if _BLD_DEBUG
+#undef DEBUG
+#define DEBUG (TRACE_message|TRACE_count|TRACE_debug)
+#else
+#ifndef DEBUG
+#define DEBUG (TRACE_message)
+#endif
+#endif
+
+/*
+ * the lower tests are transient
+ */
+
+#define TEST_count (1L<<24)
+#define TEST_hashcount (1L<<25)
+#define TEST_hashdump (1L<<26)
+#define TEST_hit (1L<<27)
+#define TEST_noinit (1L<<28)
+#define TEST_nonoise (1L<<29)
+#define TEST_noproto (1L<<30)
+
+#define TEST_INVERT (1L<<31)
+
+#define PROTO_CLASSIC (1<<0) /* classic to prototyped */
+#define PROTO_DISABLE (1<<1) /* disable conversion */
+#define PROTO_EXTERNALIZE (1<<2) /* static fun() => extern fun() */
+#define PROTO_FORCE (1<<3) /* force even if no magic */
+#define PROTO_HEADER (1<<4) /* header defines too */
+#define PROTO_INCLUDE (1<<5) /* <prototyped.h> instead */
+#define PROTO_INITIALIZED (1<<6) /* internal initialization */
+#define PROTO_LINESYNC (1<<7) /* force standalone line syncs */
+#define PROTO_NOPRAGMA (1<<8) /* delete pragma prototyped */
+#define PROTO_PASS (1<<9) /* pass blocks if no magic */
+#define PROTO_PLUSPLUS (1<<10) /* extern () -> extern (...) */
+#define PROTO_RETAIN (1<<11) /* defines retained after close */
+#define PROTO_TEST (1<<12) /* enable test code */
+
+#define PROTO_USER (1<<13) /* first user flag */
+
+#define SEARCH_EXISTS 0 /* ppsearch for existence */
+#define SEARCH_HOSTED (1<<0) /* search hosted dirs only */
+#define SEARCH_IGNORE (1<<1) /* ignore if not found */
+#define SEARCH_INCLUDE (1<<2) /* ppsearch for include */
+#define SEARCH_VENDOR (1<<3) /* search vendor dirs only */
+#define SEARCH_USER (1<<4) /* first user flag */
+
+#define STYLE_gnu (1<<0) /* gnu style args */
+
+#define IN_c (1<<0) /* C language file */
+#define IN_defguard (1<<1) /* did multiple include check */
+#define IN_disable (1<<2) /* saved state&DISABLE */
+#define IN_endguard (1<<3) /* did multiple include check */
+#define IN_eof (1<<4) /* reached EOF */
+#define IN_expand (1<<5) /* ppexpand buffer */
+#define IN_flush (1<<6) /* flush stdout on file_refill()*/
+#define IN_hosted (1<<7) /* saved mode&HOSTED */
+#define IN_ignoreline (1<<8) /* ignore #line until file */
+#define IN_newline (1<<9) /* newline at end of last fill */
+#define IN_noguard (1<<10) /* no multiple include guard */
+#define IN_prototype (1<<11) /* ppproto() input */
+#define IN_regular (1<<12) /* regular input file */
+#define IN_static (1<<13) /* static buffer - don't free */
+#define IN_sync (1<<14) /* line sync required on pop */
+#define IN_tokens (1L<<15)/* non-space tokens encountered */
+
+#define OPT_GLOBAL (1<<0) /* pp: pass optional */
+#define OPT_PASS (1<<1) /* pass on */
+
+struct ppsymbol;
+struct ppindex;
+
+typedef char* (*PPBUILTIN)(char*, const char*, const char*);
+typedef void (*PPCOMMENT)(const char*, const char*, const char*, int);
+typedef void (*PPINCREF)(const char*, const char*, int, int);
+typedef void (*PPLINESYNC)(int, const char*);
+typedef void (*PPMACREF)(struct ppsymbol*, const char*, int, int, unsigned long);
+typedef int (*PPOPTARG)(int, int, const char*);
+typedef void (*PPPRAGMA)(const char*, const char*, const char*, const char*, int);
+
+struct ppinstk /* input stream stack frame */
+{
+ char* nextchr; /* next input char (first elt) */
+ struct ppinstk* next; /* next frame (for allocation) */
+ struct ppinstk* prev; /* previous frame */
+ long* control; /* control block level */
+ char* buffer; /* buffer base pointer */
+ char* file; /* saved file name */
+ char* prefix; /* directory prefix */
+ struct ppsymbol* symbol; /* macro info */
+#if CHECKPOINT
+ struct ppindex* index; /* checkpoint include index */
+ int buflen; /* buffer count */
+#endif
+ int line; /* saved line number */
+ int vendor; /* saved pp.vendor */
+ short fd; /* file descriptor */
+ short hide; /* hide index (from pp.hide) */
+ short flags; /* IN_[a-z]* flags */
+ char type; /* input type */
+};
+
+#if MACKEYARGS
+struct ppkeyarg /* pp macro keyword arg info */
+{
+ char* name; /* keyword arg name */
+ char* value; /* keyword arg value */
+};
+#endif
+
+struct pplist /* string list */
+{
+ char* value; /* string value */
+ struct pplist* next; /* next in list */
+};
+
+struct oplist /* queue op until PP_INIT */
+{
+ int op; /* PP_* op */
+ char* value; /* op value */
+ struct oplist* next; /* next op */
+};
+
+struct pphide /* hidden symbol info */
+{
+ struct ppmacro* macro; /* saved macro info */
+ unsigned long flags; /* saved symbol flags if macro */
+ int level; /* nesting level */
+};
+
+struct ppmacstk /* macro invocation stack frame */
+{
+ struct ppmacstk* next; /* next frame (for allocation) */
+ struct ppmacstk* prev; /* previous frame */
+ int line; /* line number of first arg */
+ char* arg[1]; /* arg text pointers */
+};
+
+struct ppmember /* archive member pun on ppfile */
+{
+ struct ppdirs* archive; /* archive holding file */
+ unsigned long offset; /* data offset */
+ unsigned long size; /* data size */
+};
+
+struct counter /* monitoring counters */
+{
+ int candidate; /* macro candidates */
+ int function; /* function macros */
+ int macro; /* macro hits */
+ int pplex; /* pplex() calls */
+ int push; /* input stream pushes */
+ int terminal; /* terminal states */
+ int token; /* emitted tokens */
+};
+
+struct pptuple /* tuple macro */
+{
+ struct pptuple* nomatch; /* nomatch tuple */
+ struct pptuple* match; /* match tuple */
+ char token[1]; /* matching token */
+};
+
+struct ppfileid /* physical file id */
+{
+ unsigned long st_dev; /* dev */
+ unsigned long st_ino; /* ino */
+};
+
+struct pathid /* physical file name and id */
+{
+ char* path; /* file path */
+ struct ppfileid id; /* file id */
+};
+
+#define SAMEID(a,b) ((a)->st_ino==(unsigned long)(b)->st_ino&&(a)->st_dev==(unsigned long)(b)->st_dev)
+#define SAVEID(a,b) ((a)->st_ino=(unsigned long)(b)->st_ino,(a)->st_dev=(unsigned long)(b)->st_dev)
+
+#define _PP_CONTEXT_PRIVATE_ /* ppglobals private context */ \
+ struct ppcontext* context; /* current context */ \
+ long state; /* pp state flags */ \
+ long mode; /* uncoupled pp state flags */ \
+ long option; /* option flags */ \
+ long test; /* implementation tests */ \
+ struct \
+ { \
+ Sfio_t* sp; /* FILEDEPS output stream */ \
+ long flags; /* PP_FILEDEPS flags */ \
+ } filedeps; /* FILEDEPS info */ \
+ struct ppdirs* firstdir; /* first include dir */ \
+ struct ppdirs* lastdir; /* last include dir */ \
+ int hide; /* current include hide index */ \
+ int column; /* FILEDEPS column */ \
+ int pending; /* ppline() pending output */ \
+ char* firstfile; /* ppline() first file */ \
+ char* lastfile; /* ppline() most recent file */ \
+ char* ignore; /* include ignore list file */ \
+ char* probe; /* ppdefault probe key */ \
+ Hash_table_t* filtab; /* file name hash table */ \
+ Hash_table_t* prdtab; /* predicate hash table */ \
+ char* date; /* start date string */ \
+ char* time; /* start time string */ \
+ char* maps; /* directive maps */ \
+ long ro_state; /* readonly state */ \
+ long ro_mode; /* readonly mode */ \
+ long ro_option; /* readonly option */ \
+ struct pathid cdir; /* arg C dir */ \
+ struct pathid hostdir; /* arg host dir */ \
+ char* ppdefault; /* arg default info file */ \
+ struct ppindex* firstindex; /* first include index entry */ \
+ struct ppindex* lastindex; /* last include index entry */ \
+ struct oplist* firstop; /* first arg op */ \
+ struct oplist* lastop; /* last arg op */ \
+ struct oplist* firsttx; /* first text file */ \
+ struct oplist* lasttx; /* last text file */ \
+ unsigned char arg_file; /* arg file index */ \
+ unsigned char arg_mode; /* arg mode */ \
+ unsigned char arg_style; /* arg style */ \
+ unsigned char c; /* arg C state */ \
+ unsigned char hosted; /* arg hosted state */ \
+ unsigned char ignoresrc; /* arg ignore source state */ \
+ unsigned char initialized; /* arg initialized state */ \
+ unsigned char standalone; /* arg standalone state */ \
+ unsigned char spare_1; /* padding spare */
+
+#define _PP_GLOBALS_PRIVATE_ /* ppglobals private additions */ \
+ char* checkpoint; /* checkpoint version */ \
+ int constack; /* pp.control size */ \
+ struct ppinstk* in; /* input stream stack pointer */ \
+ char* addp; /* addbuf pointer */ \
+ char* args; /* predicate args */ \
+ char* addbuf; /* ADD buffer */ \
+ char* catbuf; /* catenation buffer */ \
+ char* hdrbuf; /* HEADEREXPAND buffer */ \
+ char* hidebuf; /* pp:hide buffer */ \
+ char* path; /* full path of last #include */ \
+ char* tmpbuf; /* very temporary buffer */ \
+ char* valbuf; /* builtin macro value buffer */ \
+ char* optflags; /* OPT_* flags indexed by X_* */ \
+ int lastout; /* last output char */ \
+ /* the rest are implicitly initialized */ \
+ char* include; /* saved path of last #include */ \
+ char* prefix; /* current directory prefix */ \
+ struct ppmember* member; /* include archive member data */ \
+ int hidden; /* hidden newline count */ \
+ int hiding; /* number of symbols in hiding */ \
+ int level; /* pplex() recursion level */ \
+ struct \
+ { \
+ int input; /* pool input */ \
+ int output; /* pool output */ \
+ } pool; /* loop on input,output,error */ \
+ struct \
+ { \
+ long ro_state; /* original pp.ro_state */ \
+ long ro_mode; /* original pp.ro_mode */ \
+ long ro_option; /* original pp.ro_option */ \
+ int on; /* PP_RESET enabled */ \
+ Hash_table_t* symtab; /* original pp.symtab scope */ \
+ } reset; /* PP_RESET state */ \
+ int truncate; /* identifier truncation length */ \
+ struct ppmacstk* macp; /* top of macro actual stack */ \
+ char* maxmac; /* maximum size of macro stack */ \
+ char* mactop; /* top of current macro frame */ \
+ char* toknxt; /* '\0' of pp.token */ \
+ long* control; /* control block flags pointer */ \
+ long* maxcon; /* max control block frame */ \
+ struct oplist* chop; /* include prefix chop list */ \
+ struct ppfile* insert; /* inserted line sync file */ \
+ struct ppfile* original; /* original include name */ \
+ struct ppdirs* found; /* last successful ppsearch dir */ \
+ int vendor; /* vendor includes only */ \
+ Hash_table_t* dirtab; /* directive hash table */ \
+ Hash_table_t* strtab; /* string hash table */ \
+ PPBUILTIN builtin; /* builtin macro handler */ \
+ PPCOMMENT comment; /* pass along comments */ \
+ PPINCREF incref; /* include file push/return */ \
+ PPLINESYNC linesync; /* pass along line sync info */ \
+ PPLINESYNC olinesync; /* original linesync value */ \
+ PPMACREF macref; /* called on macro def/ref */ \
+ PPOPTARG optarg; /* unknown option arg handler */ \
+ PPPRAGMA pragma; /* pass along unknown pragmas */ \
+ struct counter counter; /* monitoring counters */ \
+ char funbuf[256]; /* last __FUNCTION__ */
+
+#define _PP_SYMBOL_PRIVATE_ /* ppsymbol private additions */ \
+ struct pphide* hidden; /* hidden symbol info */
+
+#if MACKEYARGS
+#define _PP_MACRO_PRIVATE_ /* ppmacro private additions */ \
+ struct pptuple* tuple; /* tuple macro */ \
+ union \
+ { \
+ char* formal; /* normal formals list */ \
+ struct ppkeyarg* key; /* keyword formals table */ \
+ } args; /* macro args info */ \
+ int size; /* body size */
+#define formals args.formal /* formal argument list */
+#define formkeys args.key /* formal keyword argument list */
+#else
+#define _PP_MACRO_PRIVATE_ /* ppmacro private additions */ \
+ struct pptuple* tuple; /* tuple macro */ \
+ char* formals; /* formal argument list */ \
+ int size; /* body size */
+#endif
+
+#define _PP_DIRS_PRIVATE_ /* ppdirs private additions */ \
+ unsigned char c; /* files here are C language */ \
+ unsigned char index; /* prefix,local,standard index */ \
+ unsigned char type; /* dir type */ \
+ union \
+ { \
+ char* buffer; /* TYPE_BUFFER buffer */ \
+ Sfio_t* sp; /* archive stream */ \
+ struct ppdirs* subdir; /* subdir list */ \
+ } info; /* type info */ \
+ struct ppfileid id; /* directory id */ \
+
+#if !PROTOMAIN
+#include <ast.h>
+#include <error.h>
+#endif
+
+#undef newof
+#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
+
+#include "pp.h"
+#include "ppdef.h"
+#include "ppkey.h"
+
+#undef setstate /* random clash! */
+
+/*
+ * DEBUG is encoded with the following bits
+ */
+
+#define TRACE_message 01
+#define TRACE_count 02
+#define TRACE_debug 04
+
+#if DEBUG && !lint
+#define PANIC (ERROR_PANIC|ERROR_SOURCE|ERROR_SYSTEM),__FILE__,__LINE__
+#else
+#define PANIC ERROR_PANIC
+#endif
+
+#if DEBUG & TRACE_count
+#define count(x) pp.counter.x++
+#else
+#define count(x)
+#endif
+
+#if DEBUG & TRACE_message
+#define message(x) do { if (tracing) error x; } while (0)
+#else
+#define message(x)
+#endif
+
+#if DEBUG & TRACE_debug
+#define debug(x) do { if (tracing) error x; } while (0)
+#else
+#define debug(x)
+#endif
+
+/*
+ * note that MEMCPY advances the associated pointers
+ */
+
+#define MEMCPY(to,fr,n) \
+ do switch(n) \
+ { default : memcpy(to,fr,n); to += n; fr += n; break; \
+ case 7 : *to++ = *fr++; \
+ case 6 : *to++ = *fr++; \
+ case 5 : *to++ = *fr++; \
+ case 4 : *to++ = *fr++; \
+ case 3 : *to++ = *fr++; \
+ case 2 : *to++ = *fr++; \
+ case 1 : *to++ = *fr++; \
+ case 0 : break; \
+ } while (0)
+
+#define NEWDIRECTIVE (-1)
+
+#undef dirname
+#undef error
+
+#define dirname(x) ppkeyname(x,1)
+#define error pperror
+#define keyname(x) ppkeyname(x,0)
+#define nextframe(m,p) (m->next=m+(p-(char*)m+sizeof(struct ppmacstk)-1)/sizeof(struct ppmacstk)+1)
+#define popframe(m) (m=m->prev)
+#define pptokchr(c) pptokstr(NiL,(c))
+#define pushcontrol() do { if (pp.control++ >= pp.maxcon) ppnest(); } while (0)
+#define pushframe(m) (m->next->prev=m,m=m->next)
+#define setmode(m,v) ((v)?(pp.mode|=(m)):(pp.mode&=~(m)))
+#define setoption(m,v) ((v)?(pp.option|=(m)):(pp.option&=~(m)))
+#define setstate(s,v) ((v)?(pp.state|=(s)):(pp.state&=~(s)))
+#define tracing (error_info.trace<0)
+
+#define ppgetfile(x) ((struct ppfile*)hashlook(pp.filtab,x,HASH_LOOKUP,NiL))
+#define ppsetfile(x) ((struct ppfile*)hashlook(pp.filtab,x,HASH_CREATE|HASH_SIZE(sizeof(struct ppfile)),NiL))
+
+#define ppkeyget(t,n) (struct ppsymkey*)hashlook(t,n,HASH_LOOKUP,NiL)
+#define ppkeyref(t,n) (struct ppsymkey*)hashlook(t,n,HASH_LOOKUP|HASH_INTERNAL,NiL)
+#define ppkeyset(t,n) (struct ppsymkey*)hashlook(t,n,HASH_CREATE|HASH_SIZE(sizeof(struct ppsymkey)),NiL)
+
+#define MARK '@' /* internal mark */
+#define ARGOFFSET '1' /* macro arg mark offset */
+
+#define STRAPP(p,v,r) do{r=(v);while((*p++)=(*r++));}while(0)
+#define STRCOPY(p,v,r) do{r=(v);while((*p++)=(*r++));p--;}while(0)
+#define STRCOPY2(p,r) do{while((*p++)=(*r++));p--;}while(0)
+
+#define SETFILE(p,v) (p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'F',(long)v,MARK))
+#define SETLINE(p,v) (p+=sfsprintf(p,16,"%c%c%lx%c",MARK,'L',(long)v,MARK))
+
+#define peekchr() (*pp.in->nextchr)
+#define ungetchr(c) (*--pp.in->nextchr=(c))
+
+#define MAXID 255 /* maximum identifier size */
+#define MAXTOKEN PPTOKSIZ /* maximum token size */
+#define MAXFORMALS 64 /* maximum number macro formals */
+#define MAXHIDDEN 8 /* ppline if hidden>=MAXHIDDEN */
+#define DEFMACSTACK (MAXFORMALS*32*32)/* default macstack size */
+
+#define FSM_COMPATIBILITY 1 /* compatibility mode */
+#define FSM_IDADD 2 /* add to identifer set */
+#define FSM_IDDEL 3 /* delete from identifer set */
+#define FSM_INIT 4 /* initilize */
+#define FSM_MACRO 5 /* add new macro */
+#define FSM_OPSPACE 6 /* handle <binop><space>= */
+#define FSM_PLUSPLUS 7 /* C++ lexical analysis */
+#define FSM_QUOTADD 8 /* add to quote set */
+#define FSM_QUOTDEL 9 /* delete from quote set */
+
+#define IN_TOP 01 /* top level -- directives ok */
+
+#define IN_BUFFER (2|IN_TOP) /* buffer of lines */
+#define IN_COPY 2 /* macro arg (copied) */
+#define IN_EXPAND 4 /* macro arg (expanded) */
+#define IN_FILE (4|IN_TOP) /* file */
+#define IN_INIT (6|IN_TOP) /* initialization IN_BUFFER */
+#define IN_MACRO 8 /* macro text */
+#define IN_MULTILINE (8|IN_TOP) /* multi-line macro text */
+#define IN_QUOTE 10 /* "..." macro arg (copied) */
+#define IN_RESCAN (10|IN_TOP) /* directive rescan buffer */
+#define IN_SQUOTE 12 /* '...' macro arg (copied) */
+#define IN_STRING 14 /* string */
+
+#define INC_CLEAR ((struct ppsymbol*)0)
+#define INC_IGNORE ((struct ppsymbol*)pp.addbuf)
+#define INC_TEST ((struct ppsymbol*)pp.catbuf)
+
+#define INC_BOUND(n) (1<<(n))
+#define INC_MEMBER(n) (1<<((n)+INC_MAX))
+#define INC_PREFIX 0
+#define INC_LOCAL 1
+#define INC_STANDARD 2
+#define INC_VENDOR 3
+#define INC_MAX 4
+#define INC_SELF (1<<(2*INC_MAX+0))
+#define INC_EXISTS (1<<(2*INC_MAX+1))
+#define INC_LISTED (1<<(2*INC_MAX+2))
+#define INC_MAPALL (1<<(2*INC_MAX+3))
+#define INC_MAPHOSTED (1<<(2*INC_MAX+4))
+#define INC_MAPNOHOSTED (1<<(2*INC_MAX+5))
+#define INC_MAPNOLOCAL (1<<(2*INC_MAX+6))
+#define INC_HOSTED (1<<(2*INC_MAX+7))
+
+#define TYPE_ARCHIVE (1<<0)
+#define TYPE_BUFFER (1<<1)
+#define TYPE_CHECKPOINT (1<<2)
+#define TYPE_DIRECTORY (1<<3)
+#define TYPE_HOSTED (1<<4)
+#define TYPE_INCLUDE (1<<5)
+#define TYPE_VENDOR (1<<6)
+
+#define TOK_BUILTIN (1<<0) /* last token was #( */
+#define TOK_FORMAL (1<<1) /* last token was arg formal id */
+#define TOK_ID (1<<2) /* last token was identifier */
+#define TOK_TOKCAT (1<<3) /* last token was ## */
+
+#define HADELSE (1<<0) /* already had else part */
+#define KEPT (1<<1) /* already kept part of block */
+#define SKIP (1<<2) /* skip this block */
+#define BLOCKBITS 3 /* block flag bits */
+
+#define SETIFBLOCK(p) (*(p)=(*((p)-1)&SKIP)|((long)error_info.line<<BLOCKBITS))
+#define GETIFLINE(p) ((*(p)>>BLOCKBITS)&((1L<<(sizeof(long)*CHAR_BIT-BLOCKBITS))-1))
+
+#define PUSH(t,p) \
+ do \
+ { \
+ count(push); \
+ if (!pp.in->next) \
+ { \
+ pp.in->next = newof(0, struct ppinstk, 1, 0); \
+ pp.in->next->prev = pp.in; \
+ } \
+ p = pp.in = pp.in->next; \
+ p->type = t; \
+ p->flags = 0; \
+ } while (0)
+
+#define PUSH_BUFFER(f,p,n) \
+ pppush(IN_BUFFER,f,p,n)
+
+#define PUSH_COPY(p,n) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_COPY, cur); \
+ cur->line = error_info.line; \
+ error_info.line = n; \
+ cur->nextchr = p; \
+ cur->prev->symbol->flags &= ~SYM_DISABLED; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_EXPAND(p,n) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_EXPAND, cur); \
+ cur->line = error_info.line; \
+ error_info.line = n; \
+ cur->prev->symbol->flags &= ~SYM_DISABLED; \
+ cur->buffer = cur->nextchr = ppexpand(p); \
+ if (!(cur->prev->symbol->flags & SYM_MULTILINE)) \
+ cur->prev->symbol->flags |= SYM_DISABLED; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_FILE(f,d) \
+ pppush(IN_FILE,f,NiL,d)
+
+#define PUSH_INIT(f,p) \
+ pppush(IN_INIT,f,p,1)
+
+#define PUSH_MACRO(p) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_MACRO, cur); \
+ cur->symbol = p; \
+ cur->nextchr = p->macro->value; \
+ p->flags |= SYM_DISABLED; \
+ if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
+ pp.state &= ~NEWLINE; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_TUPLE(p,v) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_MACRO, cur); \
+ cur->symbol = p; \
+ cur->nextchr = v; \
+ p->flags |= SYM_DISABLED; \
+ pp.state &= ~NEWLINE; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_MULTILINE(p) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ register int n; \
+ PUSH(IN_MULTILINE, cur); \
+ cur->symbol = p; \
+ cur->flags |= IN_defguard|IN_endguard|IN_noguard; \
+ pushcontrol(); \
+ cur->control = pp.control; \
+ *pp.control = 0; \
+ cur->file = error_info.file; \
+ n = strlen(error_info.file) + strlen(((struct ppsymbol*)p)->name) + 24; \
+ error_info.file = cur->buffer = newof(0, char, n, 0); \
+ sfsprintf(error_info.file, n, "%s:%s,%d", cur->file, p->name, error_info.line); \
+ cur->line = error_info.line; \
+ error_info.line = 1; \
+ cur->nextchr = p->macro->value; \
+ if (p->flags & SYM_FUNCTION) pushframe(pp.macp); \
+ pp.state &= ~NEWLINE; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_QUOTE(p,n) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_QUOTE, cur); \
+ cur->nextchr = p; \
+ pp.state |= QUOTE; \
+ cur->line = error_info.line; \
+ error_info.line = n; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_RESCAN(p) \
+ pppush(IN_RESCAN,NiL,p,0)
+
+#define PUSH_SQUOTE(p,n) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_SQUOTE, cur); \
+ cur->nextchr = p; \
+ pp.state |= SQUOTE; \
+ cur->line = error_info.line; \
+ error_info.line = n; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_STRING(p) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_STRING, cur); \
+ cur->nextchr = p; \
+ if (pp.state & DISABLE) cur->flags |= IN_disable; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define PUSH_LINE(p) \
+ do \
+ { \
+ register struct ppinstk* cur; \
+ PUSH(IN_STRING, cur); \
+ cur->nextchr = p; \
+ pp.state |= DISABLE|NOSPACE|PASSEOF|STRIP; \
+ debug((-7, "PUSH in=%s next=%s", ppinstr(pp.in), pptokchr(*pp.in->nextchr))); \
+ } while (0)
+
+#define POP_LINE() \
+ do \
+ { \
+ debug((-7, "POP in=%s", ppinstr(pp.in))); \
+ pp.in = pp.in->prev; \
+ pp.state &= ~(DISABLE|NOSPACE|PASSEOF|STRIP); \
+ } while (0)
+
+struct ppcontext /* pp context */
+{
+ _PP_CONTEXT_PUBLIC_
+ _PP_CONTEXT_PRIVATE_
+};
+
+struct ppfile /* include file info */
+{
+ HASH_HEADER; /* this is a hash bucket too */
+ struct ppsymbol* guard; /* guard symbol */
+ struct ppfile* bound[INC_MAX]; /* include bindings */
+ int flags; /* INC_* flags */
+};
+
+#if CHECKPOINT
+
+struct ppindex /* checkpoint include index */
+{
+ struct ppindex* next; /* next in list */
+ struct ppfile* file; /* include file */
+ unsigned long begin; /* beginning output offset */
+ unsigned long end; /* ending output offset */
+};
+
+#endif
+
+struct ppsymkey /* pun for SYM_KEYWORD lex val */
+{
+ struct ppsymbol sym; /* symbol as usual */
+ int lex; /* lex value for SYM_KEYWORD */
+};
+
+#if PROTOMAIN && PROTO_STANDALONE
+
+#if defined(__STDC__) || defined(__cplusplus) || defined(c_plusplus)
+#define NiL 0
+#define NoP(x) (&x,1)
+#else
+#define NiL ((char*)0)
+#define NoP(x)
+#endif
+
+#define newof(p,t,n,x) ((p)?(t*)realloc((char*)(p),sizeof(t)*(n)+(x)):(t*)calloc(1,sizeof(t)*(n)+(x)))
+
+#define _PP_DELAY_ #
+
+_PP_DELAY_ ifdef __STDC__
+
+_PP_DELAY_ include <stdlib.h>
+_PP_DELAY_ include <unistd.h>
+_PP_DELAY_ include <time.h>
+_PP_DELAY_ include <string.h>
+
+_PP_DELAY_ else
+
+_PP_DELAY_ define size_t int
+
+extern void* realloc(void*, size_t);
+extern void* calloc(size_t, size_t);
+extern char* ctime(time_t*);
+extern void free(void*);
+
+_PP_DELAY_ ifndef O_RDONLY
+
+extern int access(const char*, int);
+extern int close(int);
+extern int creat(const char*, int);
+extern void exit(int);
+extern int link(const char*, const char*);
+extern int open(const char*, int, ...);
+extern int read(int, void*, int);
+extern time_t time(time_t*);
+extern int unlink(const char*);
+extern int write(int, const void*, int);
+
+_PP_DELAY_ endif
+
+_PP_DELAY_ endif
+
+#else
+
+/*
+ * library implementation globals
+ */
+
+#define ppassert _pp_assert
+#define ppbuiltin _pp_builtin
+#define ppcall _pp_call
+#define ppcontrol _pp_control
+#define ppdump _pp_dump
+#define ppexpand _pp_expand
+#define ppexpr _pp_expr
+#define ppfsm _pp_fsm
+#define ppinmap _pp_inmap
+#define ppinstr _pp_instr
+#define ppkeyname _pp_keyname
+#define pplexmap _pp_lexmap
+#define pplexstr _pp_lexstr
+#define ppload _pp_load
+#define ppmodestr _pp_modestr
+#define ppmultiple _pp_multiple
+#define ppnest _pp_nest
+#define ppoption _pp_option
+#define ppoptionstr _pp_optionstr
+#define pppclose _pp_pclose
+#define pppdrop _pp_pdrop
+#define pppopen _pp_popen
+#define pppread _pp_pread
+#define pppredargs _pp_predargs
+#define pppush _pp_push
+#define pprefmac _pp_refmac
+#define ppsearch _pp_search
+#define ppstatestr _pp_statestr
+#define pptokstr _pp_tokstr
+#define pptrace _pp_trace
+
+#endif
+
+extern void ppassert(int, char*, char*);
+extern void ppbuiltin(void);
+extern int ppcall(struct ppsymbol*, int);
+extern int ppcontrol(void);
+extern void ppdump(void);
+extern char* ppexpand(char*);
+extern long ppexpr(int*);
+extern void ppfsm(int, char*);
+extern char* ppinstr(struct ppinstk*);
+extern char* ppkeyname(int, int);
+extern char* pplexstr(int);
+extern void ppload(char*);
+extern void ppmapinclude(char*, char*);
+extern char* ppmodestr(long);
+extern int ppmultiple(struct ppfile*, struct ppsymbol*);
+extern void ppnest(void);
+extern int ppoption(char*);
+extern char* ppoptionstr(long);
+extern void pppclose(char*);
+extern int pppdrop(char*);
+extern char* pppopen(char*, int, char*, char*, char*, char*, int);
+extern int pppread(char*);
+extern int pppredargs(void);
+extern void pppush(int, char*, char*, int);
+extern struct ppsymbol* pprefmac(char*, int);
+extern int ppsearch(char*, int, int);
+extern char* ppstatestr(long);
+extern char* pptokstr(char*, int);
+extern void pptrace(int);
+
+#if _std_malloc
+
+#include <vmalloc.h>
+
+#undef free
+#define free(p) vmfree(Vmregion,(void*)p)
+#undef newof
+#define newof(p,t,n,x) vmnewof(Vmregion,p,t,n,x)
+#undef oldof
+#define oldof(p,t,n,x) vmoldof(Vmregion,p,t,n,x)
+#undef strdup
+#define strdup(s) vmstrdup(Vmregion,s)
+
+#endif
+
+#endif
diff --git a/usr/src/lib/libpp/common/ppline.c b/usr/src/lib/libpp/common/ppline.c
new file mode 100644
index 0000000000..8ff7c23339
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppline.c
@@ -0,0 +1,86 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common preprocessor line sync handler
+ */
+
+#include "pplib.h"
+
+void
+ppline(int line, char* file)
+{
+ char* s;
+ static char type[5];
+
+ if (pp.flags & PP_lineignore)
+ {
+ pp.flags &= ~PP_lineignore;
+ if (!(pp.flags & PP_linetype) || *pp.lineid)
+ {
+ ppline(1, file);
+ file = error_info.file;
+ }
+ else
+ type[1] = PP_sync_ignore;
+ }
+ else if (file != pp.lastfile)
+ {
+ if (!pp.firstfile)
+ pp.firstfile = file;
+ type[1] = ((pp.flags & PP_linetype) && !*pp.lineid && pp.lastfile) ? (line <= 1 ? (file == pp.firstfile ? PP_sync : PP_sync_push) : PP_sync_pop) : PP_sync;
+ pp.lastfile = file;
+ }
+ else
+ {
+ if (!(pp.flags & PP_linefile))
+ file = 0;
+ type[1] = PP_sync;
+ }
+ if (!(pp.flags & PP_linetype) || *pp.lineid || type[1] == PP_sync)
+ type[0] = 0;
+ else
+ {
+ type[0] = ' ';
+ if ((pp.flags & (PP_hosted|PP_linehosted)) == (PP_hosted|PP_linehosted))
+ {
+ type[2] = ' ';
+ type[3] = PP_sync_hosted;
+ }
+ else
+ type[2] = 0;
+ }
+
+ /*
+ * some front ends can't handle two line syncs in a row
+ */
+
+ if (pp.pending == pppendout() || pplastout() != '\n')
+ ppputchar('\n');
+ if (file)
+ ppprintf("#%s %d \"%s\"%s\n", pp.lineid, line, (pp.flags & PP_linebase) && (s = strrchr(file, '/')) ? s + 1 : file, type);
+ else
+ ppprintf("#%s %d\n", pp.lineid, line);
+ if (!pp.macref)
+ pp.pending = pppendout();
+}
diff --git a/usr/src/lib/libpp/common/ppmacref.c b/usr/src/lib/libpp/common/ppmacref.c
new file mode 100644
index 0000000000..d744f99803
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppmacref.c
@@ -0,0 +1,58 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common preprocessor macro reference handler
+ */
+
+#include "pplib.h"
+
+void
+ppmacref(struct ppsymbol* sym, char* file, int line, int type, unsigned long sum)
+{
+ register char* p;
+
+ NoP(file);
+ NoP(line);
+ p = (pp.state & (DIRECTIVE|JOINING)) == DIRECTIVE ? pp.outp : pp.addp;
+ p += sfsprintf(p, MAXTOKEN, "\n#%s %d", pp.lineid, error_info.line);
+ p += sfsprintf(p, MAXTOKEN, "\n#%s %s:%s %s %d", dirname(PRAGMA), pp.pass, keyname(X_MACREF), sym->name, type);
+ if (type > 0)
+ {
+ if (sym->macro && sym->macro->value)
+ sum = strsum(sym->macro->value, (long)sym->macro->arity);
+ p += sfsprintf(p, MAXTOKEN, " %lu", sum);
+ }
+ if ((pp.state & (DIRECTIVE|JOINING)) == DIRECTIVE)
+ {
+ pp.outp = p;
+ ppcheckout();
+ }
+ else
+ {
+ *p++ = '\n';
+ pp.addp = p;
+ pp.state |= ADD;
+ }
+ pp.pending = pppendout();
+}
diff --git a/usr/src/lib/libpp/common/ppmisc.c b/usr/src/lib/libpp/common/ppmisc.c
new file mode 100644
index 0000000000..d7b5d3730e
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppmisc.c
@@ -0,0 +1,242 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * miscellaneous preprocessor support
+ */
+
+#include "pplib.h"
+
+/*
+ * macro symbol def|ref
+ */
+
+struct ppsymbol*
+pprefmac(char* name, int ref)
+{
+ register struct ppsymbol* sym;
+
+ if (!(sym = ppsymget(pp.symtab, name)) && (ref <= REF_NORMAL && pp.macref || ref == REF_CREATE || ref == REF_DELETE && (pp.mode & (INIT|READONLY))))
+ {
+ if ((pp.state & COMPILE) && pp.truncate && strlen(name) > pp.truncate)
+ name[pp.truncate] = 0;
+ sym = ppsymset(pp.symtab, NiL);
+ }
+ if (sym && ref <= REF_NORMAL)
+ {
+ if (pp.macref) (*pp.macref)(sym, error_info.file, error_info.line, ref == REF_NORMAL && (pp.state & CONDITIONAL) ? REF_IF : ref, 0L);
+ if (!sym->macro) sym = 0;
+ }
+#if COMPATIBLE
+ if (!(pp.state & COMPATIBILITY))
+#endif
+ if (ref == REF_IF && sym && (sym->flags & SYM_PREDEFINED) && *name != '_' && !(pp.mode & (HOSTED|INACTIVE)))
+ {
+ if (pp.state & STRICT)
+ {
+ error(1, "%s: obsolete predefined symbol reference disabled", name);
+ return(0);
+ }
+ error(1, "%s: obsolete predefined symbol referenced", name);
+ }
+ return(sym);
+}
+
+/*
+ * common predicate assertion operations
+ * op is DEFINE or UNDEF
+ */
+
+void
+ppassert(int op, char* pred, char* args)
+{
+ register struct pplist* a;
+ register struct ppsymbol* sym;
+ register struct pplist* p;
+ register struct pplist* q;
+
+ if (!args) switch (op)
+ {
+ case DEFINE:
+ goto mark;
+ case UNDEF:
+ a = 0;
+ goto unmark;
+ }
+ if (a = (struct pplist*)hashget(pp.prdtab, pred))
+ {
+ p = 0;
+ q = a;
+ while (q)
+ {
+ if (streq(q->value, args))
+ {
+ if (op == DEFINE) return;
+ q = q->next;
+ if (p) p->next = q;
+ else a = q;
+ }
+ else
+ {
+ p = q;
+ q = q->next;
+ }
+ }
+ if (op == UNDEF)
+ {
+ unmark:
+ hashput(pp.prdtab, pred, a);
+ if (sym = ppsymref(pp.symtab, pred))
+ sym->flags &= ~SYM_PREDICATE;
+ return;
+ }
+ }
+ if (op == DEFINE)
+ {
+ p = newof(0, struct pplist, 1, 0);
+ p->next = a;
+ p->value = strdup(args);
+ hashput(pp.prdtab, NiL, p);
+ mark:
+ if ((pp.state & COMPILE) && pp.truncate) return;
+ if (sym = ppsymset(pp.symtab, pred))
+ sym->flags |= SYM_PREDICATE;
+ }
+}
+
+/*
+ * parse a predicate argument list
+ * the args are placed in pp.args
+ * the first non-space/paren argument token type is returned
+ * forms:
+ *
+ * predicate <identifier> type=T_ID
+ * predicate ( <identifier> ) type=T_ID
+ * predicate ( ) type=0
+ * predicate ( <balanced-paren-list> ) type=T_STRING
+ * otherwise type=<other>
+ */
+
+int
+pppredargs(void)
+{
+ register int c;
+ register int n;
+ register int type;
+ char* pptoken;
+
+ pptoken = pp.token;
+ pp.token = pp.args;
+ switch (type = pplex())
+ {
+ case '(':
+ type = 0;
+ n = 1;
+ pp.state |= HEADER;
+ pp.state &= ~STRIP;
+ c = pplex();
+ pp.state &= ~NOSPACE;
+ for (;;)
+ {
+ switch (c)
+ {
+ case '(':
+ n++;
+ break;
+ case '\n':
+ ungetchr(c);
+ error(2, "missing %d )%s in predicate argument list", n, n == 1 ? "" : "'s");
+ type = 0;
+ goto done;
+ case ')':
+ if (!--n) goto done;
+ break;
+ }
+ pp.token = pp.toknxt;
+ if (c != ' ')
+ {
+ if (type) type = T_STRING;
+ else type = (c == T_ID) ? T_ID : T_STRING;
+ }
+ c = pplex();
+ }
+ done:
+ pp.state &= ~HEADER;
+ pp.state |= NOSPACE|STRIP;
+ if (pp.token > pp.args && *(pp.token - 1) == ' ') pp.token--;
+ *pp.token = 0;
+ break;
+ case '\n':
+ ungetchr('\n');
+ type = 0;
+ break;
+ }
+ pp.token = pptoken;
+ return(type);
+}
+
+/*
+ * sync output line number
+ */
+
+int
+ppsync(void)
+{
+ long m;
+
+ if ((pp.state & (ADD|HIDDEN)))
+ {
+ if (pp.state & ADD)
+ {
+ pp.state &= ~ADD;
+ m = pp.addp - pp.addbuf;
+ pp.addp = pp.addbuf;
+ ppprintf("%-.*s", m, pp.addbuf);
+ }
+ if (pp.linesync)
+ {
+ if ((pp.state & SYNCLINE) || pp.hidden >= MAXHIDDEN)
+ {
+ pp.hidden = 0;
+ pp.state &= ~(HIDDEN|SYNCLINE);
+ if (error_info.line)
+ (*pp.linesync)(error_info.line, error_info.file);
+ }
+ else
+ {
+ m = pp.hidden;
+ pp.hidden = 0;
+ pp.state &= ~HIDDEN;
+ while (m-- > 0)
+ ppputchar('\n');
+ }
+ }
+ else
+ {
+ pp.hidden = 0;
+ pp.state &= ~HIDDEN;
+ ppputchar('\n');
+ }
+ }
+ return 0;
+}
diff --git a/usr/src/lib/libpp/common/ppop.c b/usr/src/lib/libpp/common/ppop.c
new file mode 100644
index 0000000000..86e3651864
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppop.c
@@ -0,0 +1,1553 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor library control interface
+ */
+
+#include "pplib.h"
+#include "pptab.h"
+
+#include <ls.h>
+
+#define REFONE (pp.truncate?(Hash_table_t*)0:pp.symtab)
+#define REFALL (pp.truncate?pp.dirtab:pp.symtab)
+
+#define ppiskey(t,v,p) (p=t,v>=p->value&&value<=(p+elementsof(t)-2)->value)
+
+/*
+ * set option value
+ * initialization files have lowest precedence
+ */
+
+static void
+set(register long* p, register long op, int val)
+{
+ long* r;
+
+ r = p == &pp.state ? &pp.ro_state : p == &pp.mode ? &pp.ro_mode : &pp.ro_option;
+ if (!(pp.mode & INIT) || !(pp.in->type == IN_FILE) || !(*r & op))
+ {
+ if (!pp.initialized && !(pp.mode & INIT))
+ *r |= op;
+ if (val)
+ *p |= op;
+ else
+ *p &= ~op;
+ }
+ debug((-7, "set(%s)=%s", p == &pp.state ? "state" : p == &pp.mode ? "mode" : "option", p == &pp.state ? ppstatestr(*p) : p == &pp.mode ? ppmodestr(*p) : ppoptionstr(*p)));
+}
+
+/*
+ * initialize hash table with keywords from key
+ */
+
+static void
+inithash(register Hash_table_t* tab, register struct ppkeyword* key)
+{
+ register char* s;
+
+ for (; s = key->name; key++)
+ {
+ if (!ppisid(*s))
+ s++;
+ hashput(tab, s, key->value);
+ }
+}
+
+/*
+ * return ppkeyword table name given value
+ */
+
+char*
+ppkeyname(register int value, int dir)
+{
+ register char* s;
+ register struct ppkeyword* p;
+
+ if (dir && ppiskey(directives, value, p) || !dir && (ppiskey(options, value, p) || ppiskey(predicates, value, p) || ppiskey(variables, value, p)))
+ {
+ s = (p + (value - p->value))->name;
+ return s + !ppisid(*s);
+ }
+#if DEBUG
+ error(PANIC, "no keyword table name for value=%d", value);
+#endif
+ return "UNKNOWN";
+}
+
+/*
+ * add to the include maps
+ */
+
+void
+ppmapinclude(char* file, register char* s)
+{
+ register int c;
+ register struct ppdirs* dp;
+ int fd;
+ int flags;
+ int index;
+ int token;
+ char* t;
+ char* old_file;
+ long old_state;
+ struct ppfile* fp;
+ struct ppfile* mp;
+
+ old_file = error_info.file;
+ old_state = pp.state;
+ if (s)
+ PUSH_BUFFER("mapinclude", s, 1);
+ else if (file)
+ {
+ if (*file == '-')
+ {
+ if (!error_info.file)
+ {
+ error(1, "%s: input file name required for %s ignore", file, dirname(INCLUDE));
+ return;
+ }
+ s = t = strcopy(pp.tmpbuf, error_info.file);
+ c = *++file;
+ for (;;)
+ {
+ if (s <= pp.tmpbuf || *s == '/')
+ {
+ s = t;
+ break;
+ }
+ else if (*s == c)
+ break;
+ s--;
+ }
+ strcpy(s, file);
+ file = pp.tmpbuf;
+ }
+ if ((fd = ppsearch(file, INC_LOCAL, SEARCH_INCLUDE)) < 0)
+ return;
+ PUSH_FILE(file, fd);
+ }
+ else
+ return;
+#if CATSTRINGS
+ pp.state |= (COMPILE|FILEPOP|HEADER|JOINING|STRIP|NOSPACE|PASSEOF);
+#else
+ pp.state |= (COMPILE|FILEPOP|HEADER|STRIP|NOSPACE|PASSEOF);
+#endif
+ pp.level++;
+ flags = INC_MAPALL;
+ fp = mp = 0;
+ for (;;)
+ {
+ switch (token = pplex())
+ {
+ case 0:
+ case T_STRING:
+ case T_HEADER:
+ if (fp)
+ {
+ fp->guard = INC_IGNORE;
+ for (dp = pp.firstdir->next; dp; dp = dp->next)
+ if (dp->name && (c = strlen(dp->name)) && !strncmp(dp->name, fp->name, c) && fp->name[c] == '/')
+ {
+ ppsetfile(fp->name + c + 1)->guard = INC_IGNORE;
+ break;
+ }
+ }
+ if (!token)
+ break;
+ pathcanon(pp.token, 0);
+ fp = ppsetfile(pp.token);
+ if (mp)
+ {
+ mp->flags |= flags;
+ if (streq(fp->name, "."))
+ mp->flags |= INC_MAPNOLOCAL;
+ else
+ mp->bound[index] = fp;
+
+ fp = mp = 0;
+ }
+ else
+ index = token == T_HEADER ? INC_STANDARD : INC_LOCAL;
+ continue;
+ case '=':
+ if (!(mp = fp))
+ error(3, "%s: \"name\" = \"binding\" expected");
+ fp = 0;
+ continue;
+ case '\n':
+ continue;
+ case T_ID:
+ if (streq(pp.token, "all"))
+ {
+ flags = INC_MAPALL;
+ continue;
+ }
+ else if (streq(pp.token, "hosted"))
+ {
+ flags = INC_MAPHOSTED;
+ continue;
+ }
+ else if (streq(pp.token, "nohosted"))
+ {
+ flags = INC_MAPNOHOSTED;
+ continue;
+ }
+ /*FALLTHROUGH*/
+ default:
+ error(3, "%s unexpected in %s map list", pptokstr(pp.token, 0), dirname(INCLUDE));
+ break;
+ }
+ break;
+ }
+ pp.level--;
+ error_info.file = old_file;
+ pp.state = old_state;
+}
+
+/*
+ * return non-0 if file is identical to fd
+ */
+
+static int
+identical(char* file, int fd)
+{
+ struct stat a;
+ struct stat b;
+
+ return !stat(file, &a) && !fstat(fd, &b) && a.st_dev == b.st_dev && a.st_ino == b.st_ino;
+}
+
+/*
+ * compare up to pp.truncate chars
+ *
+ * NOTE: __STD* and symbols containing ' ' are not truncated
+ */
+
+static int
+trunccomp(register char* a, register char* b)
+{
+ return !strchr(b, ' ') && !strneq(b, "__STD", 5) ? strncmp(a, b, pp.truncate) : strcmp(a, b);
+}
+
+/*
+ * hash up to pp.truncate chars
+ *
+ * NOTE: __STD* and symbols containing ' ' are not truncated
+ */
+
+static unsigned int
+trunchash(char* a)
+{
+ int n;
+
+ return memhash(a, (n = strlen(a)) > pp.truncate && !strchr(a, ' ') && !strneq(a, "__STD", 5) ? pp.truncate : n);
+}
+
+#if DEBUG & TRACE_debug
+/*
+ * append context to debug trace
+ */
+
+static int
+context(Sfio_t* sp, int level, int flags)
+{
+ static int state;
+
+ NoP(level);
+ NoP(flags);
+ if (error_info.trace <= -10 && pp.state != state)
+ {
+ state = pp.state;
+ sfprintf(sp, " %s", ppstatestr(pp.state));
+ }
+ return 1;
+}
+#endif
+
+/*
+ * reset include guard
+ */
+
+static int
+unguard(const char* name, char* v, void* handle)
+{
+ register struct ppfile* fp = (struct ppfile*)v;
+
+ fp->guard = 0;
+ return 0;
+}
+
+/*
+ * reset macro definition
+ */
+
+static void
+undefine(void* p)
+{
+ struct ppmacro* mac = ((struct ppsymbol*)p)->macro;
+
+ if (mac)
+ {
+ if (mac->formals)
+ free(mac->formals);
+ free(mac->value);
+ free(mac);
+ }
+}
+
+/*
+ * pp operations
+ *
+ * NOTE: PP_INIT must be done before the first pplex() call
+ * PP_DONE must be done after the last pplex() call
+ * PP_INIT-PP_DONE must be done for each new PP_INPUT
+ */
+
+void
+ppop(int op, ...)
+{
+ va_list ap;
+ register char* p;
+ register struct ppkeyword* kp;
+ register char* s;
+ int c;
+ long n;
+ char* t;
+ struct ppdirs* dp;
+ struct ppdirs* hp;
+ struct ppsymkey* key;
+ struct oplist* xp;
+ Sfio_t* sp;
+ struct stat st;
+ PPCOMMENT ppcomment;
+ PPLINESYNC pplinesync;
+
+ static int initialized;
+
+ va_start(ap, op);
+ switch (op)
+ {
+ case PP_ASSERT:
+ case PP_DEFINE:
+ case PP_DIRECTIVE:
+ case PP_OPTION:
+ case PP_READ:
+ case PP_UNDEF:
+ if (pp.initialized)
+ goto before;
+ if ((p = va_arg(ap, char*)) && *p)
+ {
+ if (pp.lastop)
+ pp.lastop = (pp.lastop->next = newof(0, struct oplist, 1, 0));
+ else
+ pp.firstop = pp.lastop = newof(0, struct oplist, 1, 0);
+ pp.lastop->op = op;
+ pp.lastop->value = p;
+ }
+ break;
+ case PP_BUILTIN:
+ pp.builtin = va_arg(ap, PPBUILTIN);
+ break;
+ case PP_CDIR:
+ p = va_arg(ap, char*);
+ c = va_arg(ap, int);
+ pp.cdir.path = 0;
+ if (!p)
+ pp.c = c;
+ else if (streq(p, "-"))
+ {
+ pp.c = c;
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ dp->c = c;
+ }
+ else if (!pp.c)
+ {
+ if (!*p || stat((pathcanon(p, 0), p), &st))
+ pp.c = c;
+ else
+ {
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ {
+ if (!pp.c && (dp->c || dp->name && SAMEID(&dp->id, &st)))
+ pp.c = 1;
+ dp->c = pp.c == 1;
+ }
+ if (!pp.c)
+ {
+ pp.cdir.path = p;
+ SAVEID(&pp.cdir.id, &st);
+ }
+ }
+ }
+ break;
+ case PP_CHOP:
+ if (p = va_arg(ap, char*))
+ {
+ c = strlen(p);
+ xp = newof(0, struct oplist, 1, c + 1);
+ xp->value = ((char*)xp) + sizeof(struct oplist);
+ s = xp->value;
+ c = *p++;
+ while (*p && *p != c)
+ *s++ = *p++;
+ *s++ = '/';
+ xp->op = s - xp->value;
+ *s++ = 0;
+ if (*p && *++p && *p != c)
+ {
+ while (*p && *p != c)
+ *s++ = *p++;
+ *s++ = '/';
+ }
+ *s = 0;
+ xp->next = pp.chop;
+ pp.chop = xp;
+ }
+ break;
+ case PP_COMMENT:
+ if (pp.comment = va_arg(ap, PPCOMMENT))
+ pp.flags |= PP_comment;
+ else
+ pp.flags &= ~PP_comment;
+ break;
+ case PP_COMPATIBILITY:
+ set(&pp.state, COMPATIBILITY, va_arg(ap, int));
+#if COMPATIBLE
+ if (pp.initialized)
+ ppfsm(FSM_COMPATIBILITY, NiL);
+#else
+ if (pp.state & COMPATIBILITY)
+ error(3, "preprocessor not compiled with compatibility dialect enabled [COMPATIBLE]");
+#endif
+ if (pp.state & COMPATIBILITY)
+ pp.flags |= PP_compatibility;
+ else
+ pp.flags &= ~PP_compatibility;
+ break;
+ case PP_COMPILE:
+ if (pp.initialized)
+ goto before;
+ pp.state |= COMPILE;
+ if (!pp.symtab)
+ pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0);
+ if (kp = va_arg(ap, struct ppkeyword*))
+ for (; s = kp->name; kp++)
+ {
+ n = SYM_LEX;
+ switch (*s)
+ {
+ case '-':
+ s++;
+ break;
+ case '+':
+ s++;
+ if (!(pp.option & PLUSPLUS))
+ break;
+ /*FALLTHROUGH*/
+ default:
+ n |= SYM_KEYWORD;
+ break;
+ }
+ if (key = ppkeyset(pp.symtab, s))
+ {
+ key->sym.flags = n;
+ key->lex = kp->value;
+ }
+ }
+ break;
+ case PP_DEBUG:
+ error_info.trace = va_arg(ap, int);
+ break;
+ case PP_DEFAULT:
+ if (p = va_arg(ap, char*))
+ p = strdup(p);
+ if (pp.ppdefault)
+ free(pp.ppdefault);
+ pp.ppdefault = p;
+ break;
+ case PP_DONE:
+#if CHECKPOINT
+ if (pp.mode & DUMP)
+ ppdump();
+#endif
+ if (pp.mode & FILEDEPS)
+ {
+ sfputc(pp.filedeps.sp, '\n');
+ if (pp.filedeps.sp == sfstdout)
+ sfsync(pp.filedeps.sp);
+ else
+ sfclose(pp.filedeps.sp);
+ }
+ if (pp.state & STANDALONE)
+ {
+ if ((pp.state & (NOTEXT|HIDDEN)) == HIDDEN && pplastout() != '\n')
+ ppputchar('\n');
+ ppflushout();
+ }
+ error_info.file = 0;
+ break;
+ case PP_DUMP:
+ set(&pp.mode, DUMP, va_arg(ap, int));
+#if !CHECKPOINT
+ if (pp.mode & DUMP)
+ error(3, "preprocessor not compiled with checkpoint enabled [CHECKPOINT]");
+#endif
+ break;
+ case PP_FILEDEPS:
+ if (n = va_arg(ap, int))
+ pp.filedeps.flags |= n;
+ else
+ pp.filedeps.flags = 0;
+ break;
+ case PP_FILENAME:
+ error_info.file = va_arg(ap, char*);
+ break;
+ case PP_HOSTDIR:
+ if (!(pp.mode & INIT))
+ pp.ro_mode |= HOSTED;
+ else if (pp.ro_mode & HOSTED)
+ break;
+ pp.ro_mode |= INIT;
+ p = va_arg(ap, char*);
+ c = va_arg(ap, int);
+ pp.hostdir.path = 0;
+ if (!p)
+ pp.hosted = c;
+ else if (streq(p, "-"))
+ {
+ if (pp.initialized)
+ set(&pp.mode, HOSTED, c);
+ else
+ {
+ pp.hosted = c ? 1 : 2;
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ if (pp.hosted == 1)
+ dp->type |= TYPE_HOSTED;
+ else
+ dp->type &= ~TYPE_HOSTED;
+ }
+ }
+ else if (!pp.hosted)
+ {
+ if (!*p || stat((pathcanon(p, 0), p), &st))
+ pp.hosted = 1;
+ else
+ {
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ {
+ if (!pp.hosted && ((dp->type & TYPE_HOSTED) || dp->name && SAMEID(&dp->id, &st)))
+ pp.hosted = 1;
+ if (pp.hosted == 1)
+ dp->type |= TYPE_HOSTED;
+ else
+ dp->type &= ~TYPE_HOSTED;
+ }
+ if (!pp.hosted)
+ {
+ pp.hostdir.path = p;
+ SAVEID(&pp.hostdir.id, &st);
+ }
+ }
+ }
+ break;
+ case PP_ID:
+ p = va_arg(ap, char*);
+ c = va_arg(ap, int);
+ if (p)
+ ppfsm(c ? FSM_IDADD : FSM_IDDEL, p);
+ break;
+ case PP_IGNORE:
+ if (p = va_arg(ap, char*))
+ {
+ pathcanon(p, 0);
+ ppsetfile(p)->guard = INC_IGNORE;
+ message((-3, "%s: ignore", p));
+ }
+ break;
+ case PP_IGNORELIST:
+ if (pp.initialized)
+ goto before;
+ pp.ignore = va_arg(ap, char*);
+ break;
+ case PP_INCLUDE:
+ if ((p = va_arg(ap, char*)) && *p)
+ {
+ pathcanon(p, 0);
+ if (stat(p, &st))
+ break;
+ for (dp = pp.stddirs; dp = dp->next;)
+ if (dp->name && SAMEID(&dp->id, &st))
+ break;
+ if (pp.cdir.path && SAMEID(&pp.cdir.id, &st))
+ {
+ pp.cdir.path = 0;
+ pp.c = 1;
+ }
+ if (pp.hostdir.path && SAMEID(&pp.hostdir.id, &st))
+ {
+ pp.hostdir.path = 0;
+ pp.hosted = 1;
+ }
+ if ((pp.mode & INIT) && !(pp.ro_mode & INIT))
+ pp.hosted = 1;
+ c = dp && dp->c || pp.c == 1;
+ n = dp && (dp->type & TYPE_HOSTED) || pp.hosted == 1;
+ if (!dp || dp == pp.lastdir->next)
+ {
+ if (dp)
+ {
+ c = dp->c;
+ n = dp->type & TYPE_HOSTED;
+ }
+ dp = newof(0, struct ppdirs, 1, 0);
+ dp->name = p;
+ SAVEID(&dp->id, &st);
+ dp->type |= TYPE_INCLUDE;
+ dp->index = INC_LOCAL + pp.ignoresrc != 0;
+ dp->next = pp.lastdir->next;
+ pp.lastdir = pp.lastdir->next = dp;
+ }
+ dp->c = c;
+ if (n)
+ dp->type |= TYPE_HOSTED;
+ else
+ dp->type &= ~TYPE_HOSTED;
+ }
+ break;
+ case PP_INCREF:
+ pp.incref = va_arg(ap, PPINCREF);
+ break;
+ case PP_RESET:
+ pp.reset.on = 1;
+ break;
+ case PP_INIT:
+ if (pp.initialized)
+ {
+ error_info.errors = 0;
+ error_info.warnings = 0;
+ }
+ else
+ {
+ /*
+ * context initialization
+ */
+
+ if (!initialized)
+ {
+ /*
+ * out of malloc is fatal
+ */
+
+ memfatal();
+
+ /*
+ * initialize the error message interface
+ */
+
+ error_info.version = (char*)pp.version;
+#if DEBUG & TRACE_debug
+ error_info.auxilliary = context;
+ pptrace(0);
+#endif
+
+ /*
+ * initialize pplex tables
+ */
+
+ ppfsm(FSM_INIT, NiL);
+
+ /*
+ * fixed macro stack size -- room for improvement
+ */
+
+ pp.macp = newof(0, struct ppmacstk, DEFMACSTACK, 0);
+ pp.macp->next = pp.macp + 1;
+ pp.maxmac = (char*)pp.macp + DEFMACSTACK;
+ initialized = 1;
+
+ /*
+ * initial include/if control stack
+ */
+
+ pp.control = newof(0, long, pp.constack, 0);
+ pp.maxcon = pp.control + pp.constack - 1;
+ }
+
+ /*
+ * validate modes
+ */
+
+ switch (pp.arg_mode)
+ {
+ case 'a':
+ case 'C':
+ ppop(PP_COMPATIBILITY, 0);
+ ppop(PP_TRANSITION, 1);
+ break;
+ case 'A':
+ case 'c':
+ ppop(PP_COMPATIBILITY, 0);
+ ppop(PP_STRICT, 1);
+ break;
+ case 'f':
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_PLUSPLUS, 1);
+ ppop(PP_TRANSITION, 1);
+ break;
+ case 'F':
+ ppop(PP_COMPATIBILITY, 0);
+ ppop(PP_PLUSPLUS, 1);
+ break;
+ case 'k':
+ case 's':
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_STRICT, 1);
+ break;
+ case 'o':
+ case 'O':
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_TRANSITION, 0);
+ break;
+ case 't':
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_TRANSITION, 1);
+ break;
+ }
+ if (!(pp.arg_style & STYLE_gnu))
+ ppop(PP_PEDANTIC, 1);
+ if (pp.state & PASSTHROUGH)
+ {
+ if (pp.state & COMPILE)
+ {
+ pp.state &= ~PASSTHROUGH;
+ error(1, "passthrough ignored for compile");
+ }
+ else
+ {
+ ppop(PP_COMPATIBILITY, 1);
+ ppop(PP_HOSTDIR, "-", 1);
+ ppop(PP_SPACEOUT, 1);
+ set(&pp.state, DISABLE, va_arg(ap, int));
+ }
+ }
+
+ /*
+ * create the hash tables
+ */
+
+ if (!pp.symtab)
+ pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0);
+ if (!pp.dirtab)
+ {
+ pp.dirtab = hashalloc(REFONE, HASH_name, "directives", 0);
+ inithash(pp.dirtab, directives);
+ }
+ if (!pp.filtab)
+ pp.filtab = hashalloc(REFALL, HASH_name, "files", 0);
+ if (!pp.prdtab)
+ pp.prdtab = hashalloc(REFALL, HASH_name, "predicates", 0);
+ if (!pp.strtab)
+ {
+ pp.strtab = hashalloc(REFALL, HASH_name, "strings", 0);
+ inithash(pp.strtab, options);
+ inithash(pp.strtab, predicates);
+ inithash(pp.strtab, variables);
+ }
+ pp.optflags[X_PROTOTYPED] = OPT_GLOBAL;
+ pp.optflags[X_SYSTEM_HEADER] = OPT_GLOBAL|OPT_PASS;
+
+ /*
+ * mark macros that are builtin predicates
+ */
+
+ for (kp = predicates; s = kp->name; kp++)
+ {
+ if (!ppisid(*s))
+ s++;
+ ppassert(DEFINE, s, 0);
+ }
+
+ /*
+ * the remaining entry names must be allocated
+ */
+
+ hashset(pp.dirtab, HASH_ALLOCATE);
+ hashset(pp.filtab, HASH_ALLOCATE);
+ hashset(pp.prdtab, HASH_ALLOCATE);
+ hashset(pp.strtab, HASH_ALLOCATE);
+ hashset(pp.symtab, HASH_ALLOCATE);
+ if (pp.test & TEST_nonoise)
+ {
+ c = error_info.trace;
+ error_info.trace = 0;
+ }
+#if DEBUG
+ if (!(pp.test & TEST_noinit))
+ {
+#endif
+
+ /*
+ * compose, push and read the builtin initialization script
+ */
+
+ if (!(sp = sfstropen()))
+ error(3, "temporary buffer allocation error");
+ sfprintf(sp,
+"\
+#%s %s:%s \"/#<assert> /\" \"/assert /%s #/\"\n\
+#%s %s:%s \"/#<unassert> /\" \"/unassert /%s #/\"\n\
+",
+ dirname(PRAGMA),
+ pp.pass,
+ keyname(X_MAP),
+ dirname(DEFINE),
+ dirname(PRAGMA),
+ pp.pass,
+ keyname(X_MAP),
+ dirname(UNDEF));
+ if (pp.ppdefault && *pp.ppdefault)
+ {
+ if (pp.probe)
+ {
+ c = pp.lastdir->next->type;
+ pp.lastdir->next->type = 0;
+ }
+ if (ppsearch(pp.ppdefault, T_STRING, SEARCH_EXISTS) < 0)
+ {
+ free(pp.ppdefault);
+ if (!(pp.ppdefault = pathprobe(pp.path, NiL, "C", pp.pass, pp.probe ? pp.probe : PPPROBE, 0)))
+ error(1, "cannot determine default definitions for %s", pp.probe ? pp.probe : PPPROBE);
+ }
+ if (pp.ppdefault)
+ sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.ppdefault);
+ if (pp.probe)
+ pp.lastdir->next->type = c;
+ }
+ while (pp.firstop)
+ {
+ switch (pp.firstop->op)
+ {
+ case PP_ASSERT:
+ sfprintf(sp, "#%s #%s\n", dirname(DEFINE), pp.firstop->value);
+ break;
+ case PP_DEFINE:
+ if (*pp.firstop->value == '#')
+ sfprintf(sp, "#%s %s\n", dirname(DEFINE), pp.firstop->value);
+ else
+ {
+ if (s = strchr(pp.firstop->value, '='))
+ sfprintf(sp, "#%s %-.*s %s\n", dirname(DEFINE), s - pp.firstop->value, pp.firstop->value, s + 1);
+ else
+ sfprintf(sp, "#%s %s 1\n", dirname(DEFINE), pp.firstop->value);
+ }
+ break;
+ case PP_DIRECTIVE:
+ sfprintf(sp, "#%s\n", pp.firstop->value);
+ break;
+ case PP_OPTION:
+ if (s = strchr(pp.firstop->value, '='))
+ sfprintf(sp, "#%s %s:%-.*s %s\n", dirname(PRAGMA), pp.pass, s - pp.firstop->value, pp.firstop->value, s + 1);
+ else
+ sfprintf(sp, "#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.firstop->value);
+ break;
+ case PP_READ:
+ sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.firstop->value);
+ break;
+ case PP_UNDEF:
+ sfprintf(sp, "#%s %s\n", dirname(UNDEF), pp.firstop->value);
+ break;
+ }
+ pp.lastop = pp.firstop;
+ pp.firstop = pp.firstop->next;
+ free(pp.lastop);
+ }
+ sfprintf(sp,
+"\
+#%s %s:%s\n\
+#%s %s:%s\n\
+#%s !#%s(%s)\n\
+#%s !#%s(%s) || #%s(%s)\n\
+"
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_BUILTIN)
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_PREDEFINED)
+ , dirname(IF)
+ , keyname(X_OPTION)
+ , keyname(X_PLUSPLUS)
+ , dirname(IF)
+ , keyname(X_OPTION)
+ , keyname(X_COMPATIBILITY)
+ , keyname(X_OPTION)
+ , keyname(X_TRANSITION)
+ );
+ sfprintf(sp,
+"\
+#%s __STDC__\n\
+#%s __STDC__ #(STDC)\n\
+#%s\n\
+#%s #%s(%s)\n\
+#%s %s:%s\n\
+#%s %s:%s\n\
+#%s __STRICT__ 1\n\
+#%s\n\
+#%s\n\
+"
+ , dirname(IFNDEF)
+ , dirname(DEFINE)
+ , dirname(ENDIF)
+ , dirname(IF)
+ , keyname(X_OPTION)
+ , keyname(X_STRICT)
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_ALLMULTIPLE)
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_READONLY)
+ , dirname(DEFINE)
+ , dirname(ENDIF)
+ , dirname(ENDIF)
+ );
+ for (kp = readonlys; s = kp->name; kp++)
+ {
+ if (!ppisid(*s))
+ s++;
+ sfprintf(sp, "#%s %s\n", dirname(UNDEF), s);
+ }
+ sfprintf(sp,
+"\
+#%s\n\
+#%s __STDPP__ 1\n\
+#%s %s:no%s\n\
+"
+ , dirname(ENDIF)
+ , dirname(DEFINE)
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_PREDEFINED)
+ );
+ if (!pp.truncate)
+ sfprintf(sp,
+"\
+#%s __STDPP__directive #(%s)\n\
+"
+ , dirname(DEFINE)
+ , keyname(V_DIRECTIVE)
+ );
+ for (kp = variables; s = kp->name; kp++)
+ if (ppisid(*s) || *s++ == '+')
+ {
+ t = *s == '_' ? "" : "__";
+ sfprintf(sp, "#%s %s%s%s #(%s)\n" , dirname(DEFINE), t, s, t, s);
+ }
+ sfprintf(sp,
+"\
+#%s %s:no%s\n\
+#%s %s:no%s\n\
+"
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_READONLY)
+ , dirname(PRAGMA)
+ , pp.pass
+ , keyname(X_BUILTIN)
+ );
+ t = sfstruse(sp);
+ debug((-9, "\n/* begin initialization */\n%s/* end initialization */", t));
+ ppcomment = pp.comment;
+ pp.comment = 0;
+ pplinesync = pp.linesync;
+ pp.linesync = 0;
+ PUSH_INIT(pp.pass, t);
+ pp.mode |= INIT;
+ while (pplex());
+ pp.mode &= ~INIT;
+ pp.comment = ppcomment;
+ pp.linesync = pplinesync;
+ pp.prefix = 0;
+ sfstrclose(sp);
+ if (error_info.trace)
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ message((-1, "include directory %s%s%s%s", dp->name, (dp->type & TYPE_VENDOR) ? " [VENDOR]" : "", (dp->type & TYPE_HOSTED) ? " [HOSTED]" : "", dp->c ? " [C]" : ""));
+#if DEBUG
+ }
+ if (pp.test & TEST_nonoise)
+ error_info.trace = c;
+#endif
+ {
+ /*
+ * this is sleazy but at least it's
+ * hidden in the library
+ */
+#include <preroot.h>
+#if FS_PREROOT
+ struct pplist* preroot;
+
+ if ((preroot = (struct pplist*)hashget(pp.prdtab, "preroot")))
+ setpreroot(NiL, preroot->value);
+#endif
+ }
+ if (pp.ignoresrc)
+ {
+ if (pp.ignoresrc > 1 && pp.stddirs != pp.firstdir)
+ error(1, "directories up to and including %s are for \"...\" include files only", pp.stddirs->name);
+ pp.lcldirs = pp.lcldirs->next;
+ }
+ if (pp.ignore)
+ {
+ if (*pp.ignore)
+ ppmapinclude(pp.ignore, NiL);
+ else
+ pp.ignore = 0;
+ }
+ if (pp.standalone)
+ pp.state |= STANDALONE;
+#if COMPATIBLE
+ ppfsm(FSM_COMPATIBILITY, NiL);
+#endif
+ ppfsm(FSM_PLUSPLUS, NiL);
+ pp.initialized = 1;
+ if (pp.reset.on)
+ {
+ pp.reset.symtab = pp.symtab;
+ pp.symtab = 0;
+ pp.reset.ro_state = pp.ro_state;
+ pp.reset.ro_mode = pp.ro_mode;
+ pp.reset.ro_option = pp.ro_option;
+ }
+ }
+ if (pp.reset.on)
+ {
+ if (pp.symtab)
+ {
+ hashwalk(pp.filtab, 0, unguard, NiL);
+ hashfree(pp.symtab);
+ }
+ pp.symtab = hashalloc(NiL, HASH_name, "symbols", HASH_free, undefine, HASH_set, HASH_ALLOCATE|HASH_BUCKET, 0);
+ hashview(pp.symtab, pp.reset.symtab);
+ pp.ro_state = pp.reset.ro_state;
+ pp.ro_mode = pp.reset.ro_mode;
+ pp.ro_option = pp.reset.ro_option;
+ }
+#if CHECKPOINT
+ if (pp.mode & DUMP)
+ {
+ if (!pp.pragma)
+ error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA));
+ (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1);
+ }
+#endif
+ if (n = pp.filedeps.flags)
+ {
+ if (!(n & PP_deps_file))
+ {
+ pp.state |= NOTEXT;
+ pp.option |= KEEPNOTEXT;
+ pp.linesync = 0;
+ }
+ if (n & PP_deps_generated)
+ pp.mode |= GENDEPS;
+ if (n & PP_deps_local)
+ pp.mode &= ~HEADERDEPS;
+ else if (!(pp.mode & FILEDEPS))
+ pp.mode |= HEADERDEPS;
+ pp.mode |= FILEDEPS;
+ }
+
+ /*
+ * push the main input file -- special case for hosted mark
+ */
+
+ if (pp.firstdir->type & TYPE_HOSTED)
+ pp.mode |= MARKHOSTED;
+ else
+ pp.mode &= ~MARKHOSTED;
+#if CHECKPOINT
+ if (!(pp.mode & DUMP))
+#endif
+ {
+ if (!(p = error_info.file))
+ p = "";
+ else
+ {
+ error_info.file = 0;
+ if (*p)
+ {
+ pathcanon(p, 0);
+ p = ppsetfile(p)->name;
+ }
+ }
+ PUSH_FILE(p, 0);
+ }
+ if (pp.mode & FILEDEPS)
+ {
+ if (s = strrchr(error_info.file, '/'))
+ s++;
+ else
+ s = error_info.file;
+ if (!*s)
+ s = "-";
+ s = strcpy(pp.tmpbuf, s);
+ if ((t = p = strrchr(s, '.')) && (*++p == 'c' || *p == 'C'))
+ {
+ if (c = *++p)
+ while (*++p == c);
+ if (*p)
+ t = 0;
+ else
+ t++;
+ }
+ if (!t)
+ {
+ t = s + strlen(s);
+ *t++ = '.';
+ }
+ *(t + 1) = 0;
+ if (pp.state & NOTEXT)
+ pp.filedeps.sp = sfstdout;
+ else
+ {
+ *t = 'd';
+ if (!(pp.filedeps.sp = sfopen(NiL, s, "w")))
+ error(ERROR_SYSTEM|3, "%s: cannot create", s);
+ }
+ *t = 'o';
+ pp.column = sfprintf(pp.filedeps.sp, "%s :", s);
+ if (*error_info.file)
+ pp.column += sfprintf(pp.filedeps.sp, " %s", error_info.file);
+ }
+ if (xp = pp.firsttx)
+ {
+ if (!(sp = sfstropen()))
+ error(3, "temporary buffer allocation error");
+ while (xp)
+ {
+ sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), xp->value);
+ xp = xp->next;
+ }
+ t = sfstruse(sp);
+ PUSH_BUFFER("options", t, 1);
+ sfstrclose(sp);
+ }
+ break;
+ case PP_INPUT:
+#if CHECKPOINT && POOL
+ if (!(pp.mode & DUMP) || pp.pool.input)
+#else
+#if CHECKPOINT
+ if (!(pp.mode & DUMP))
+#else
+#if POOL
+ if (pp.pool.input)
+#endif
+#endif
+#endif
+ {
+ p = va_arg(ap, char*);
+ if (!error_info.file)
+ error_info.file = p;
+ close(0);
+ if (open(p, O_RDONLY) != 0)
+ error(ERROR_SYSTEM|3, "%s: cannot read", p);
+ if (strmatch(p, "*.(s|S|as|AS|asm|ASM)"))
+ {
+ set(&pp.mode, CATLITERAL, 0);
+ ppop(PP_SPACEOUT, 1);
+ }
+ break;
+ }
+ /*FALLTHROUGH*/
+ case PP_TEXT:
+ if (pp.initialized)
+ goto before;
+ if ((p = va_arg(ap, char*)) && *p)
+ {
+ if (pp.lasttx)
+ pp.lasttx = pp.lasttx->next = newof(0, struct oplist, 1, 0);
+ else
+ pp.firsttx = pp.lasttx = newof(0, struct oplist, 1, 0);
+ pp.lasttx->op = op;
+ pp.lasttx->value = p;
+ }
+ break;
+ case PP_KEYARGS:
+ if (pp.initialized)
+ goto before;
+ set(&pp.option, KEYARGS, va_arg(ap, int));
+ if (pp.option & KEYARGS)
+#if MACKEYARGS
+ set(&pp.mode, CATLITERAL, 1);
+#else
+ error(3, "preprocessor not compiled with macro keyword arguments enabled [MACKEYARGS]");
+#endif
+ break;
+ case PP_LINE:
+ pp.linesync = va_arg(ap, PPLINESYNC);
+ break;
+ case PP_LINEBASE:
+ if (va_arg(ap, int))
+ pp.flags |= PP_linebase;
+ else
+ pp.flags &= ~PP_linebase;
+ break;
+ case PP_LINEFILE:
+ if (va_arg(ap, int))
+ pp.flags |= PP_linefile;
+ else
+ pp.flags &= ~PP_linefile;
+ break;
+ case PP_LINEID:
+ if (!(p = va_arg(ap, char*)))
+ pp.lineid = "";
+ else if (*p != '-')
+ pp.lineid = strdup(p);
+ else
+ pp.option |= IGNORELINE;
+ break;
+ case PP_LINETYPE:
+ if ((n = va_arg(ap, int)) >= 1)
+ pp.flags |= PP_linetype;
+ else
+ pp.flags &= ~PP_linetype;
+ if (n >= 2)
+ pp.flags |= PP_linehosted;
+ else
+ pp.flags &= ~PP_linehosted;
+ break;
+ case PP_LOCAL:
+ if (pp.initialized)
+ goto before;
+ pp.ignoresrc++;
+ pp.stddirs = pp.lastdir;
+ if (!(pp.ro_option & PREFIX))
+ pp.option &= ~PREFIX;
+ break;
+ case PP_MACREF:
+ pp.macref = va_arg(ap, PPMACREF);
+ break;
+ case PP_MULTIPLE:
+ set(&pp.mode, ALLMULTIPLE, va_arg(ap, int));
+ break;
+ case PP_NOHASH:
+ set(&pp.option, NOHASH, va_arg(ap, int));
+ break;
+ case PP_NOISE:
+ op = va_arg(ap, int);
+ set(&pp.option, NOISE, op);
+ set(&pp.option, NOISEFILTER, op < 0);
+ break;
+ case PP_OPTARG:
+ pp.optarg = va_arg(ap, PPOPTARG);
+ break;
+ case PP_OUTPUT:
+ pp.outfile = va_arg(ap, char*);
+ if (identical(pp.outfile, 0))
+ error(3, "%s: identical to input", pp.outfile);
+ close(1);
+ if (open(pp.outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1)
+ error(ERROR_SYSTEM|3, "%s: cannot create", pp.outfile);
+ break;
+ case PP_PASSTHROUGH:
+ if (!(pp.state & COMPILE))
+ set(&pp.state, PASSTHROUGH, va_arg(ap, int));
+ break;
+ case PP_PEDANTIC:
+ set(&pp.mode, PEDANTIC, va_arg(ap, int));
+ break;
+ case PP_PLUSCOMMENT:
+ set(&pp.option, PLUSCOMMENT, va_arg(ap, int));
+ if (pp.initialized)
+ ppfsm(FSM_PLUSPLUS, NiL);
+ break;
+ case PP_PLUSPLUS:
+ set(&pp.option, PLUSPLUS, va_arg(ap, int));
+ set(&pp.option, PLUSCOMMENT, va_arg(ap, int));
+ if (pp.initialized)
+ ppfsm(FSM_PLUSPLUS, NiL);
+ break;
+ case PP_POOL:
+ if (pp.initialized)
+ goto before;
+ if (va_arg(ap, int))
+ {
+#if POOL
+ pp.pool.input = dup(0);
+ pp.pool.output = dup(1);
+ p = "/dev/null";
+ if (!identical(p, 0))
+ {
+ if (!identical(p, 1))
+ ppop(PP_OUTPUT, p);
+ ppop(PP_INPUT, p);
+ }
+#else
+ error(3, "preprocessor not compiled with input pool enabled [POOL]");
+#endif
+ }
+ break;
+ case PP_PRAGMA:
+ pp.pragma = va_arg(ap, PPPRAGMA);
+ break;
+ case PP_PRAGMAFLAGS:
+ if (p = va_arg(ap, char*))
+ {
+ n = OPT_GLOBAL;
+ if (*p == '-')
+ p++;
+ else
+ n |= OPT_PASS;
+ if ((c = (int)hashref(pp.strtab, p)) > 0 && c <= X_last_option)
+ pp.optflags[c] = n;
+ }
+ break;
+ case PP_PROBE:
+ pp.probe = va_arg(ap, char*);
+ break;
+ case PP_QUOTE:
+ p = va_arg(ap, char*);
+ c = va_arg(ap, int);
+ if (p)
+ ppfsm(c ? FSM_QUOTADD : FSM_QUOTDEL, p);
+ break;
+ case PP_REGUARD:
+ set(&pp.option, REGUARD, va_arg(ap, int));
+ break;
+ case PP_RESERVED:
+ if ((pp.state & COMPILE) && (p = va_arg(ap, char*)))
+ {
+ if (!(sp = sfstropen()))
+ error(3, "temporary buffer allocation error");
+ sfputr(sp, p, -1);
+ p = sfstruse(sp);
+ if (s = strchr(p, '='))
+ *s++ = 0;
+ else
+ s = p;
+ while (*s == '_')
+ s++;
+ for (t = s + strlen(s); t > s && *(t - 1) == '_'; t--);
+ if (*t == '_')
+ *t = 0;
+ else
+ t = 0;
+ op = ((key = ppkeyref(pp.symtab, s)) && (key->sym.flags & SYM_LEX)) ? key->lex : T_NOISE;
+ if (pp.test & 0x0400)
+ error(1, "reserved#1 `%s' %d", s, op);
+ if (t)
+ *t = '_';
+ if (!(key = ppkeyget(pp.symtab, p)))
+ key = ppkeyset(pp.symtab, NiL);
+ else if (!(key->sym.flags & SYM_LEX))
+ {
+ struct ppsymbol tmp;
+
+ tmp = key->sym;
+ hashlook(pp.symtab, p, HASH_DELETE, NiL);
+ key = ppkeyset(pp.symtab, NiL);
+ key->sym.flags = tmp.flags;
+ key->sym.macro = tmp.macro;
+ key->sym.value = tmp.value;
+ key->sym.hidden = tmp.hidden;
+ }
+ if (!(key->sym.flags & SYM_KEYWORD))
+ {
+ key->sym.flags |= SYM_KEYWORD|SYM_LEX;
+ key->lex = op;
+ if (pp.test & 0x0400)
+ error(1, "reserved#2 `%s' %d", p, op);
+ }
+ sfstrclose(sp);
+ }
+ break;
+ case PP_SPACEOUT:
+ set(&pp.state, SPACEOUT, va_arg(ap, int));
+ break;
+ case PP_STANDALONE:
+ if (pp.initialized)
+ goto before;
+ pp.standalone = 1;
+ break;
+ case PP_STANDARD:
+ if ((pp.lastdir->next->name = ((p = va_arg(ap, char*)) && *p) ? p : NiL) && !stat(p, &st))
+ SAVEID(&pp.lastdir->next->id, &st);
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ if (dp->name)
+ for (hp = pp.firstdir; hp != dp; hp = hp->next)
+ if (hp->name && SAMEID(&hp->id, &dp->id))
+ {
+ hp->c = dp->c;
+ if (dp->type & TYPE_HOSTED)
+ hp->type |= TYPE_HOSTED;
+ else
+ hp->type &= ~TYPE_HOSTED;
+ }
+ break;
+ case PP_STRICT:
+ set(&pp.state, TRANSITION, 0);
+ pp.flags &= ~PP_transition;
+ set(&pp.state, STRICT, va_arg(ap, int));
+ if (pp.state & STRICT)
+ pp.flags |= PP_strict;
+ else
+ pp.flags &= ~PP_strict;
+ break;
+ case PP_TEST:
+ if (p = va_arg(ap, char*))
+ for (;;)
+ {
+ while (*p == ' ' || *p == '\t') p++;
+ for (s = p; n = *s; s++)
+ if (n == ',' || n == ' ' || n == '\t')
+ {
+ *s++ = 0;
+ break;
+ }
+ if (!*p)
+ break;
+ n = 0;
+ if (*p == 'n' && *(p + 1) == 'o')
+ {
+ p += 2;
+ op = 0;
+ }
+ else
+ op = 1;
+ if (streq(p, "count"))
+ n = TEST_count;
+ else if (streq(p, "hashcount"))
+ n = TEST_hashcount;
+ else if (streq(p, "hashdump"))
+ n = TEST_hashdump;
+ else if (streq(p, "hit"))
+ n = TEST_hit;
+ else if (streq(p, "init"))
+ n = TEST_noinit|TEST_INVERT;
+ else if (streq(p, "noise"))
+ n = TEST_nonoise|TEST_INVERT;
+ else if (streq(p, "proto"))
+ n = TEST_noproto|TEST_INVERT;
+ else if (*p >= '0' && *p <= '9')
+ n = strtoul(p, NiL, 0);
+ else
+ {
+ error(1, "%s: unknown test", p);
+ break;
+ }
+ if (n & TEST_INVERT)
+ {
+ n &= ~TEST_INVERT;
+ op = !op;
+ }
+ if (op)
+ pp.test |= n;
+ else
+ pp.test &= ~n;
+ p = s;
+ debug((-4, "test = 0%o", pp.test));
+ }
+ break;
+ case PP_TRANSITION:
+ set(&pp.state, STRICT, 0);
+ pp.flags &= ~PP_strict;
+ set(&pp.state, TRANSITION, va_arg(ap, int));
+ if (pp.state & TRANSITION)
+ pp.flags |= PP_transition;
+ else
+ pp.flags &= ~PP_transition;
+ break;
+ case PP_TRUNCATE:
+ if (pp.initialized)
+ goto before;
+ if ((op = va_arg(ap, int)) < 0)
+ op = 0;
+ set(&pp.option, TRUNCATE, op);
+ if (pp.option & TRUNCATE)
+ {
+ Hash_bucket_t* b;
+ Hash_bucket_t* p;
+ Hash_position_t* pos;
+ Hash_table_t* tab;
+
+ pp.truncate = op;
+ tab = pp.symtab;
+ pp.symtab = hashalloc(NiL, HASH_set, tab ? HASH_ALLOCATE : 0, HASH_compare, trunccomp, HASH_hash, trunchash, HASH_name, "truncate", 0);
+ if (tab && (pos = hashscan(tab, 0)))
+ {
+ if (p = hashnext(pos))
+ do
+ {
+ b = hashnext(pos);
+ hashlook(pp.symtab, (char*)p, HASH_BUCKET|HASH_INSTALL, NiL);
+ } while (p = b);
+ hashdone(pos);
+ }
+ }
+ else
+ pp.truncate = 0;
+ break;
+ case PP_VENDOR:
+ p = va_arg(ap, char*);
+ c = va_arg(ap, int) != 0;
+ if (!p || !*p)
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ dp->type &= ~TYPE_VENDOR;
+ else if (streq(p, "-"))
+ {
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ if (c)
+ dp->type |= TYPE_VENDOR;
+ else
+ dp->type &= ~TYPE_VENDOR;
+ }
+ else if (!stat((pathcanon(p, 0), p), &st))
+ {
+ c = 0;
+ for (dp = pp.firstdir; dp; dp = dp->next)
+ {
+ if (!c && ((dp->type & TYPE_VENDOR) || dp->name && SAMEID(&dp->id, &st)))
+ c = 1;
+ if (c)
+ dp->type |= TYPE_VENDOR;
+ else
+ dp->type &= ~TYPE_VENDOR;
+ }
+ }
+ break;
+ case PP_WARN:
+ set(&pp.state, WARN, va_arg(ap, int));
+ break;
+ before:
+ error(3, "ppop(%d): preprocessor operation must be done before PP_INIT", op);
+ break;
+ default:
+ error(3, "ppop(%d): invalid preprocessor operation", op);
+ break;
+ }
+ va_end(ap);
+}
diff --git a/usr/src/lib/libpp/common/pppragma.c b/usr/src/lib/libpp/common/pppragma.c
new file mode 100644
index 0000000000..875a17e5eb
--- /dev/null
+++ b/usr/src/lib/libpp/common/pppragma.c
@@ -0,0 +1,66 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * common preprocessor pragma handler
+ */
+
+#include "pplib.h"
+
+void
+pppragma(char* directive, char* pass, char* name, char* value, int newline)
+{
+ register int sep = 0;
+
+ ppsync();
+ if (directive)
+ {
+ ppprintf("#%s", directive);
+ sep = 1;
+ }
+ if (pass)
+ {
+ if (sep)
+ {
+ sep = 0;
+ ppprintf(" ");
+ }
+ ppprintf("%s:", pass);
+ }
+ if (name)
+ {
+ if (sep)
+ ppprintf(" ");
+ else
+ sep = 1;
+ ppprintf("%s", name);
+ }
+ if (value)
+ {
+ if (sep || pass)
+ ppprintf(" ");
+ ppprintf("%s", value);
+ }
+ if (newline)
+ ppprintf("\n");
+}
diff --git a/usr/src/lib/libpp/common/ppprintf.c b/usr/src/lib/libpp/common/ppprintf.c
new file mode 100644
index 0000000000..b8c6c77a07
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppprintf.c
@@ -0,0 +1,45 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor printf using ppputchar() buffering
+ */
+
+#include "pplib.h"
+
+int
+ppprintf(char* format, ...)
+{
+ va_list ap;
+ Sfio_t* sp;
+
+ if (!(sp = sfnew(NiL, pp.outp, MAXTOKEN, -1, SF_WRITE|SF_STRING)))
+ error(3, "temporary buffer allocation error");
+ va_start(ap, format);
+ sfvprintf(sp, format, ap);
+ va_end(ap);
+ pp.outp += sfseek(sp, 0L, SEEK_CUR);
+ ppcheckout();
+ sfclose(sp);
+ return 0;
+}
diff --git a/usr/src/lib/libpp/common/ppproto.c b/usr/src/lib/libpp/common/ppproto.c
new file mode 100644
index 0000000000..f03b2535bc
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppproto.c
@@ -0,0 +1,2549 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * convert C prototypes to ANSI, K&R and C++ styles or K&R to ANSI
+ * slips into the pp block read
+ *
+ * define PROTOMAIN for standalone proto
+ * PROTOMAIN is coded for minimal library support
+ */
+
+static const char id[] = "\n@(#)$Id: proto (AT&T Research) 2006-06-28 $\0\n";
+
+#if PROTOMAIN
+
+#include "ppfsm.c"
+
+#include <hashkey.h>
+
+#if PROTO_STANDALONE
+#undef O_RDONLY
+#endif
+
+#else
+
+#include "pplib.h"
+#include "ppfsm.h"
+
+#endif
+
+#define MAGICGEN "/* : : generated by proto : : */\n"
+
+#define MAGICDIR "pragma" /* proto magic directive */
+#define MAGICARG "prototyped" /* proto magic directive arg */
+#define MAGICOFF "noticed" /* no notice if found in pragma */
+#define MAGICTOP 64 /* must be in these top lines */
+#define NOTICED "Copyright" /* no notice if found in magic */
+
+struct proto /* proto buffer state */
+{
+ int brace; /* {..} level */
+ int call; /* call level */
+ int fd; /* input file descriptor */
+ char* file; /* input file name */
+ long flags; /* coupled flags */
+ long options; /* uncoupled flags */
+ char* package; /* header package */
+ int line; /* input line count */
+ int test; /* testing */
+
+ char* tp; /* input token base */
+
+ int iz; /* input buffer size */
+ char* ib; /* input buffer base */
+ char* ip; /* input buffer pointer */
+
+ int oz; /* output buffer size */
+ char* ob; /* output buffer base */
+ char* op; /* output buffer pointer */
+ char* ox; /* output buffer externalize */
+
+ char cc[3]; /* beg mid end comment char */
+ char pushback[4]; /* pushback area for caller */
+
+ char variadic[256]; /* variadic args buffer */
+
+ /* output buffer */
+ /* slide buffer */
+ /* input buffer */
+};
+
+/*
+ * proto is separate from pp so these undef's are ok
+ */
+
+#undef CLASSIC
+#define CLASSIC (1L<<0)
+#undef DECLARE
+#define DECLARE (1L<<1)
+#undef DEFINE
+#define DEFINE (1L<<2)
+#undef DIRECTIVE
+#define DIRECTIVE (1L<<3)
+#undef ERROR
+#define ERROR (1L<<4)
+#undef EXTERN
+#define EXTERN (1L<<5)
+#undef EXTERNALIZE
+#define EXTERNALIZE (1L<<6)
+#undef IDID
+#define IDID (1L<<7)
+#undef INDIRECT
+#define INDIRECT (1L<<8)
+#undef INIT
+#define INIT (1L<<9)
+#undef INIT_DEFINE
+#define INIT_DEFINE (1L<<10)
+#undef INIT_INCLUDE
+#define INIT_INCLUDE (1L<<11)
+#undef JUNK
+#define JUNK (1L<<12)
+#undef LINESYNC
+#define LINESYNC (1L<<13)
+#undef MANGLE
+#define MANGLE (1L<<14)
+#undef MATCH
+#define MATCH (1L<<15)
+#undef MORE
+#define MORE (1L<<16)
+#undef OTHER
+#define OTHER (1L<<17)
+#undef PASS
+#define PASS (1L<<18)
+#undef PLUSONLY
+#define PLUSONLY (1L<<19)
+#undef PLUSPLUS
+#define PLUSPLUS (1L<<20)
+#undef RECURSIVE
+#define RECURSIVE (1L<<21)
+#undef SHARP
+#define SHARP (1L<<22)
+#undef SKIP
+#define SKIP (1L<<23)
+#undef SLIDE
+#define SLIDE (1L<<24)
+#undef TOKENS
+#define TOKENS (1L<<25)
+#undef TYPEDEF
+#define TYPEDEF (1L<<26)
+#undef VARIADIC
+#define VARIADIC (1L<<27)
+#undef VARIADIC2
+#define VARIADIC2 (1L<<28)
+#undef YACC
+#define YACC (1L<<29)
+#undef YACCSPLIT
+#define YACCSPLIT (1L<<30)
+#undef YACC2
+#define YACC2 (1L<<31)
+
+#undef GLOBAL
+#define GLOBAL (MORE)
+
+#undef REGULAR
+#define REGULAR (1L<<0)
+
+#ifndef CHUNK
+#define CHUNK 1024
+#endif
+#define BLOCK (8*CHUNK)
+
+#define T_VA_START (N_TOKEN+1)
+
+#define RESERVED(b,e,n) ((((long)(b))<<16)|(((long)(e))<<8)|((long)(n)))
+
+/*
+ * generate integer
+ * pointer to end returned
+ */
+
+static char*
+number(register char* p, register long n)
+{
+ register long d;
+
+ for (d = 1000000; d > 1; d /= 10)
+ if (n >= d) *p++ = '0' + (n / d) % 10;
+ *p++ = '0' + n % 10;
+ return p;
+}
+
+#if PROTOMAIN
+
+static int errors;
+
+#if PROTO_STANDALONE
+
+/*
+ * namespace pollution forces us to claim parts of libc
+ */
+
+#undef memcpy
+#define memcpy(t,f,n) memcopy(t,f,n)
+#undef strcpy
+#define strcpy(t,f) strcopy(t,f)
+#undef strlen
+#define strlen(s) sstrlen(s)
+#undef strncmp
+#define strncmp(s,t,n) sstrncmp(s,t,n)
+
+/*
+ * environmentally safe strlen()
+ */
+
+static int
+sstrlen(register const char* s)
+{
+ register const char* b;
+
+ for (b = s; *s; s++);
+ return s - b;
+}
+
+/*
+ * environmentally safe strncmp()
+ */
+
+static int
+sstrncmp(register const char* s, register char* t, register int n)
+{
+ register const char* e = s + n;
+
+ while (s < e)
+ {
+ if (*s != *t || !*s)
+ return *s - *t;
+ s++;
+ t++;
+ }
+ return 0;
+}
+
+/*
+ * strcpy() except pointer to end returned
+ */
+
+static char*
+strcopy(register char* s, register const char* t)
+{
+ while (*s++ = *t++);
+ return s - 1;
+}
+
+#endif
+
+static void
+proto_error(char* iob, int level, char* msg, char* arg)
+{
+ register char* p;
+ char buf[1024];
+
+ p = strcopy(buf, "proto: ");
+ if (iob)
+ {
+ register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
+
+ if (proto->line)
+ {
+ if (proto->file)
+ {
+ *p++ = '"';
+ p = strcopy(p, proto->file);
+ *p++ = '"';
+ *p++ = ',';
+ *p++ = ' ';
+ }
+ p = strcopy(p, "line ");
+ p = number(p, proto->line);
+ }
+ else if (proto->file)
+ p = strcopy(p, proto->file);
+ }
+ else
+ {
+ p = strcopy(p, msg);
+ msg = arg;
+ arg = 0;
+ }
+ if (*(p - 1) != ' ')
+ {
+ *p++ = ':';
+ *p++ = ' ';
+ }
+ if (level == 1)
+ p = strcopy(p, "warning: ");
+ p = strcopy(p, msg);
+ if (arg)
+ {
+ *p++ = ' ';
+ p = strcopy(p, arg);
+ }
+ *p++ = '\n';
+ write(2, buf, p - buf);
+ if (level >= 3)
+ exit(level - 2);
+ if (level >= 2)
+ errors++;
+}
+
+/*
+ * memcpy() but pointer to end returned
+ */
+
+static char*
+memcopy(register char* s, register char* t, int n)
+{
+ register char* e = t + n;
+
+ while (t < e) *s++ = *t++;
+ return s;
+}
+
+#include "../libast/port/astlicense.c"
+
+#else
+
+#define memcopy(s,t,n) (((char*)memcpy(s,t,n))+(n))
+
+#endif
+
+/*
+ * generate line sync
+ * pointer to end returned
+ */
+
+static char*
+linesync(register struct proto* proto, register char* p, register long n)
+{
+#if PROTOMAIN
+ if (proto->flags & LINESYNC)
+#endif
+ {
+#if PROTOMAIN
+ p = strcopy(p, "\n#line ");
+#else
+ p = strcopy(p, "\n# ");
+#endif
+ p = number(p, n);
+ *p++ = '\n';
+ }
+ return p;
+}
+
+/*
+ * output init header
+ * pointer to end returned
+ */
+
+static char*
+init(struct proto* proto, char* op, int flags)
+{
+ register char* s;
+
+ if (flags & INIT_DEFINE)
+ {
+ op = strcopy(op, "\
+\n\
+#if !defined(__PROTO__)\n\
+# if defined(__STDC__) || defined(__cplusplus) || defined(_proto) || defined(c_plusplus)\n\
+# if defined(__cplusplus)\n\
+# define __LINKAGE__ \"C\"\n\
+# else\n\
+# define __LINKAGE__\n\
+# endif\n\
+# define __STDARG__\n\
+# define __PROTO__(x) x\n\
+# define __OTORP__(x)\n\
+# define __PARAM__(n,o) n\n\
+# if !defined(__STDC__) && !defined(__cplusplus)\n\
+# if !defined(c_plusplus)\n\
+# define const\n\
+# endif\n\
+# define signed\n\
+# define void int\n\
+# define volatile\n\
+# define __V_ char\n\
+# else\n\
+# define __V_ void\n\
+# endif\n\
+# else\n\
+# define __PROTO__(x) ()\n\
+# define __OTORP__(x) x\n\
+# define __PARAM__(n,o) o\n\
+# define __LINKAGE__\n\
+# define __V_ char\n\
+# define const\n\
+# define signed\n\
+# define void int\n\
+# define volatile\n\
+# endif\n\
+# define __MANGLE__ __LINKAGE__\n\
+# if defined(__cplusplus) || defined(c_plusplus)\n\
+# define __VARARG__ ...\n\
+# else\n\
+# define __VARARG__\n\
+# endif\n\
+# if defined(__STDARG__)\n\
+# define __VA_START__(p,a) va_start(p,a)\n\
+# else\n\
+# define __VA_START__(p,a) va_start(p)\n\
+# endif\n\
+# if !defined(__INLINE__)\n\
+# if defined(__cplusplus)\n\
+# define __INLINE__ extern __MANGLE__ inline\n\
+# else\n\
+# if defined(_WIN32) && !defined(__GNUC__)\n\
+# define __INLINE__ __inline\n\
+# endif\n\
+# endif\n\
+# endif\n\
+#endif\n\
+#if !defined(__LINKAGE__)\n\
+#define __LINKAGE__ /* 2004-08-11 transition */\n\
+#endif\n\
+");
+ }
+ else
+ op = strcopy(op, "\
+\n\
+#if !defined(__PROTO__)\n\
+#include <prototyped.h>\n\
+#endif\n\
+#if !defined(__LINKAGE__)\n\
+#define __LINKAGE__ /* 2004-08-11 transition */\n\
+#endif\n\
+");
+ if (proto->package)
+ {
+ s = "\
+#ifndef __MANGLE_%_DATA__\n\
+# ifdef _BLD_%\n\
+# ifdef __EXPORT__\n\
+# define __MANGLE_%_DATA__ __MANGLE__ __EXPORT__\n\
+# else\n\
+# define __MANGLE_%_DATA__ __MANGLE__\n\
+# endif\n\
+# define __MANGLE_%_FUNC__ __MANGLE__\n\
+# else\n\
+# ifdef __IMPORT__\n\
+# define __MANGLE_%_DATA__ __MANGLE__ __IMPORT__\n\
+# else\n\
+# define __MANGLE_%_DATA__ __MANGLE__\n\
+# endif\n\
+# define __MANGLE_%_FUNC__ __MANGLE__\n\
+# endif\n\
+#endif\n\
+";
+ for (;;)
+ {
+ switch (*op++ = *s++)
+ {
+ case 0:
+ op--;
+ break;
+ case '%':
+ op = strcopy(op - 1, proto->package);
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ }
+ return op;
+}
+
+#define BACKOUT() (op=ko)
+#define CACHE() do{CACHEIN();CACHEOUT();call=proto->call;}while(0)
+#define CACHEIN() (ip=proto->ip)
+#define CACHEOUT() (op=proto->op)
+#define GETCHR() (*(unsigned char*)ip++)
+#define KEEPOUT() (ko=op)
+#define LASTOUT() (*(op-1))
+#define PUTCHR(c) (*op++=(c))
+#define SYNC() do{SYNCIN();SYNCOUT();proto->flags&=~(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->flags|=flags&(EXTERN|INIT|OTHER|VARIADIC|VARIADIC2);proto->call=call;}while(0)
+#define SYNCIN() (proto->ip=ip)
+#define SYNCOUT() (proto->op=op)
+#define UNGETCHR() (ip--)
+#define UNPUTCHR() (op--)
+
+/*
+ * advance to the next non-space character
+ */
+
+static char*
+nns(register char* s)
+{
+ while (*s == ' ' || *s == '\t' || *s == '\n')
+ s++;
+ return s;
+}
+
+#define DIR_if 01
+#define DIR_el 02
+#define DIR_en 03
+#define DIR 03
+
+/*
+ * update directive mask
+ */
+
+static int
+directive(register char* s, int dir)
+{
+ switch (*(s = nns(s)))
+ {
+ case 'e':
+ case 'i':
+ dir <<= 2;
+ switch (*++s)
+ {
+ case 'f':
+ dir |= DIR_if;
+ break;
+ case 'l':
+ dir |= DIR_el;
+ break;
+ case 'n':
+ dir |= DIR_en;
+ break;
+ }
+ break;
+ }
+ return dir;
+}
+
+/*
+ * the tokenizer
+ * top level calls loop until EOB
+ * recursive calls just return the next token
+ */
+
+static int
+lex(register struct proto* proto, register long flags)
+{
+ register char* ip;
+ register char* op;
+ register int c;
+ register int state;
+ register short* rp;
+ char* m;
+ char* e;
+ char* t;
+ char* bp;
+ char* v;
+ char* im;
+ char* ko;
+ char* aom;
+ int n;
+ int line;
+ int quot;
+ int brack;
+ int sub;
+ int x;
+ int vc;
+
+ char* ie = 0;
+ char* om = 0;
+ char* aim = 0;
+ char* aie = 0;
+ char* func = 0;
+ int call = 0;
+ int dir = 0;
+ int group = 0;
+ int last = 0;
+ int paren = 0;
+#if PROTOMAIN
+ char* qe = 0;
+ int qn = 0;
+ int args = 0;
+#endif
+
+ CACHE();
+#if PROTOMAIN
+ if (flags & EXTERN) KEEPOUT();
+#endif
+ fsm_start:
+ proto->tp = ip;
+ state = PROTO;
+ bp = ip;
+ do
+ {
+ rp = fsm[state];
+ fsm_get:
+ while (!(state = rp[c = GETCHR()]));
+ fsm_next:
+ ;
+ } while (state > 0);
+ if ((n = ip - bp - 1) > 0)
+ {
+ ip = bp;
+ MEMCPY(op, ip, n);
+ ip++;
+ }
+ state = ~state;
+ fsm_terminal:
+ switch (TERM(state))
+ {
+ case S_CHR:
+ if (op > proto->ob && *(op - 1) == '=' && (op == proto->ob + 1 || *(op - 2) != '=')) switch (c)
+ {
+ case '+':
+ case '-':
+ case '*':
+ case '&':
+ PUTCHR(' ');
+ break;
+ }
+ PUTCHR(c);
+ break;
+
+ case S_CHRB:
+ UNGETCHR();
+ c = LASTOUT();
+ break;
+
+ case S_COMMENT:
+ switch (c)
+ {
+ case '\n':
+ if (INCOMMENTXX(rp)) goto fsm_newline;
+ PUTCHR(c);
+ proto->line++;
+ rp = fsm[COM2];
+ break;
+ case '/':
+#if PROTOMAIN
+ if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
+ else
+#endif
+ PUTCHR(c);
+ if (INCOMMENTXX(rp))
+ {
+ rp = fsm[COM5];
+ break;
+ }
+ goto fsm_start;
+ case EOF:
+ break;
+ default:
+#if PROTOMAIN
+ if ((flags & (EXTERN|MATCH)) == EXTERN) BACKOUT();
+ else
+#endif
+ PUTCHR(c);
+ rp = fsm[INCOMMENTXX(rp) ? COM5 : COM3];
+ break;
+ }
+ bp = ip;
+ goto fsm_get;
+
+ case S_EOB:
+ if (c)
+ {
+ if (state = fsm[TERMINAL][INDEX(rp)+1])
+ goto fsm_terminal;
+ SYNC();
+ return 0;
+ }
+ UNGETCHR();
+ fsm_eob:
+ if ((flags & (DECLARE|GLOBAL|RECURSIVE)) == GLOBAL && (proto->flags & MORE))
+ {
+#if PROTOMAIN
+ if (!(flags & EXTERN)) /* XXX */
+#endif
+ flags |= SLIDE;
+ c = ip - proto->ib;
+ if (!(flags & MATCH))
+ im = proto->tp;
+ if (ip > proto->ib)
+ {
+ n = ip - im;
+ if (ip - n < proto->ib)
+ proto->flags |= ERROR;
+ memcopy(proto->ib - n, ip - n, n);
+ ip = proto->ib;
+ }
+ proto->tp -= c;
+ if (flags & MATCH)
+ {
+ im -= c;
+ ie -= c;
+ }
+ if (aim)
+ aim -= c;
+ if (aie)
+ aie -= c;
+ if ((n = read(proto->fd, ip, proto->iz)) > 0)
+ {
+ if ((proto->options & REGULAR) && n < proto->iz)
+ {
+ proto->flags &= ~MORE;
+ close(proto->fd);
+ }
+ *(ip + n) = 0;
+ if (state & SPLICE)
+ goto fsm_splice;
+ bp = ip;
+ goto fsm_get;
+ }
+ *ip = 0;
+ proto->flags &= ~MORE;
+ close(proto->fd);
+ }
+ if (state & SPLICE)
+ goto fsm_splice;
+ /* NOTE: RECURSIVE lex() should really SLIDE too */
+ if (!(flags & RECURSIVE) && (state = rp[c = EOF]))
+ {
+ bp = ip;
+ goto fsm_next;
+ }
+ SYNC();
+ return 0;
+
+ case S_LITBEG:
+ quot = c;
+#if PROTOMAIN
+ if (c == '"' && qe)
+ {
+ for (n = 0, t = qe + 1; t < op && (*t == ' ' || *t == '\t' || *t == '\n' && ++n || *t >= 'A' && *t <= 'Z' || *t == '_'); t++);
+ if (t == op)
+ {
+ op = qe;
+ qe = 0;
+ qn = n;
+ }
+ else PUTCHR(c);
+ }
+ else
+#endif
+ PUTCHR(c);
+ rp = fsm[LIT1];
+ bp = ip;
+ goto fsm_get;
+
+ case S_LITEND:
+ if (c == quot)
+ {
+#if PROTOMAIN
+ if (!(flags & DIRECTIVE))
+ qe = (c == '"') ? op : (char*)0;
+#endif
+ PUTCHR(c);
+#if PROTOMAIN
+ while (qn > 0)
+ {
+ qn--;
+ PUTCHR('\n');
+ }
+#endif
+ }
+ else if (c != '\n' && c != EOF)
+ {
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+ }
+ else
+ {
+#if PROTOMAIN
+ while (qn > 0)
+ {
+ qn--;
+ PUTCHR('\n');
+ }
+#endif
+ UNGETCHR();
+ }
+ c = T_INVALID;
+ break;
+
+ case S_LITESC:
+#if PROTOMAIN
+ if (flags & CLASSIC) PUTCHR(c);
+ else
+#endif
+ switch (c)
+ {
+ case 'a':
+ n = CC_bel;
+ goto fsm_oct;
+ case 'E':
+ n = CC_esc;
+ goto fsm_oct;
+ case 'v':
+ n = CC_vt;
+ goto fsm_oct;
+ case 'x':
+ SYNC();
+ lex(proto, (flags & GLOBAL) | RECURSIVE);
+ for (n = x = 0; (c = GETCHR()), x < 3; x++) switch (c)
+ {
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ case '8': case '9':
+ n = (n << 4) + c - '0';
+ break;
+ case 'a': case 'b': case 'c': case 'd':
+ case 'e': case 'f':
+ n = (n << 4) + c - 'a' + 10;
+ break;
+ case 'A': case 'B': case 'C': case 'D':
+ case 'E': case 'F':
+ n = (n << 4) + c - 'A' + 10;
+ break;
+ default:
+ goto fsm_hex;
+ }
+ fsm_hex:
+ UNGETCHR();
+ fsm_oct:
+ PUTCHR(((n >> 6) & 07) + '0');
+ PUTCHR(((n >> 3) & 07) + '0');
+ PUTCHR((n & 07) + '0');
+ break;
+ default:
+ PUTCHR(c);
+ break;
+ }
+ rp = fsm[LIT1];
+ bp = ip;
+ goto fsm_get;
+
+ case S_MACRO:
+ UNGETCHR();
+#if PROTOMAIN
+ if ((flags & EXTERN) && *proto->tp == 's' && !strncmp(proto->tp, "static", 6))
+ {
+ c = T_EXTERN;
+ break;
+ }
+#endif
+ if (*proto->tp == '_' && !strncmp(proto->tp, "__STDPP__directive", 6)) c = '#';
+ else c = T_ID;
+
+ break;
+
+ case S_NL:
+ fsm_newline:
+ proto->line++;
+#if PROTOMAIN
+ if (flags & EXTERN)
+ {
+ if (op != proto->ob && LASTOUT() != ' ' && LASTOUT() != '\n')
+ PUTCHR(' ');
+ }
+ else
+#endif
+ PUTCHR(c);
+ if (flags & DIRECTIVE)
+ {
+#if PROTOMAIN
+ if (flags & CLASSIC)
+ {
+ if (flags & EXTERN) BACKOUT();
+ if (flags & JUNK)
+ {
+ *(ip - 1) = 0;
+ op = strcopy(om, "/* ");
+ op = strcopy(op, im);
+ op = strcopy(op, " */\n");
+ }
+ flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|JUNK|MATCH|SHARP|TYPEDEF);
+ }
+ else
+#endif
+ {
+ if ((flags & (DEFINE|SHARP)) == (DEFINE|SHARP))
+ {
+ *(ip - 1) = 0;
+ op = strcopy(om, "#if defined(__STDC__) || defined(__STDPP__)\n");
+ op = strcopy(op, im);
+ op = strcopy(op, "\n#else\n");
+ bp = ip;
+ ip = im;
+ *op++ = *ip++;
+ while (*op = *ip++)
+ if (*op++ == '#' && *ip != '(')
+ {
+ op--;
+ while (*--op == ' ' || *op == '\t');
+ if (*ip == '#')
+ {
+ op = strcopy(op + 1, "/**/");
+ while (*++ip == ' ' || *ip == '\t');
+ }
+ else
+ {
+ if (*op != '"') *++op = '"';
+ op++;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ while ((c = *ip) >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || c >= '0' && c <= '9' || c == '_') *op++ = *ip++;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip == '"') ip++;
+ else *op++ = '"';
+ }
+ }
+ ip = bp;
+ op = strcopy(op, "\n#endif\n");
+ op = linesync(proto, op, proto->line);
+ }
+ flags &= ~(DEFINE|DIRECTIVE|IDID|INDIRECT|MATCH|OTHER|SHARP|SKIP|TOKENS|TYPEDEF);
+ }
+ call = 0;
+ group = 0;
+ paren = 0;
+ last = '\n';
+ }
+ if (paren == 0 && (flags & (MATCH|RECURSIVE|SKIP|SLIDE)) == SLIDE)
+ {
+#if PROTOMAIN
+ if (flags & EXTERN) BACKOUT();
+#endif
+ SYNC();
+ return 0;
+ }
+ goto fsm_start;
+
+ case S_QUAL:
+ PUTCHR(c);
+ rp = fsm[NEXT(state)];
+ bp = ip;
+ goto fsm_get;
+
+ case S_TOK:
+ PUTCHR(c);
+ c = TYPE(state);
+ break;
+
+ case S_TOKB:
+ UNGETCHR();
+ c = TYPE(state);
+ break;
+
+ case S_RESERVED:
+ UNGETCHR();
+ c = T_ID;
+ if (!(flags & DECLARE)) switch (RESERVED(*proto->tp, *(ip - 1), ip - proto->tp))
+ {
+ case RESERVED('N', 'N', 3):
+ if (proto->tp[1] == 'o')
+ c = T_DO;
+ break;
+ case RESERVED('d', 'o', 2):
+ c = T_DO;
+ break;
+ case RESERVED('e', 'e', 4):
+ if (!(flags & RECURSIVE) && (flags & (DIRECTIVE|TOKENS)) != DIRECTIVE && !strncmp(proto->tp, "else", 4))
+ {
+ c = T_ELSE;
+ goto fsm_id;
+ }
+ break;
+ case RESERVED('e', 'n', 6):
+ if (!strncmp(proto->tp, "extern", 6))
+ c = T_EXTERN;
+ break;
+ case RESERVED('f', 'r', 3):
+ if (!(flags & RECURSIVE) && !strncmp(proto->tp, "for", 3))
+ {
+ c = T_FOR;
+ goto fsm_id;
+ }
+ break;
+ case RESERVED('i', 'f', 2):
+ c = T_IF;
+ break;
+ case RESERVED('i', 'e', 6):
+ if (!strncmp(proto->tp, "inline", 6) && !(flags & (MATCH|SKIP|TOKENS|TYPEDEF)) && proto->brace == 0 && paren == 0 && group == 0 && (last == ';' || last == '}' || last == '\n' || last == 0))
+ {
+ flags |= SKIP;
+ SYNC();
+ line = proto->line;
+ op = strcopy(op - 6, "__INLINE__");
+ SYNC();
+ }
+ break;
+ case RESERVED('r', 'n', 6):
+ if (!(flags & RECURSIVE) && !strncmp(proto->tp, "return", 6))
+ {
+ c = T_RETURN;
+ goto fsm_id;
+ }
+ break;
+ case RESERVED('s', 'c', 6):
+ if ((proto->options & EXTERNALIZE) && !strncmp(proto->tp, "static", 6))
+ {
+ proto->ox = op - 6;
+ flags |= EXTERNALIZE;
+ }
+ break;
+ case RESERVED('t', 'f', 7):
+ if (!(flags & RECURSIVE) && !strncmp(proto->tp, "typedef", 7))
+ {
+ flags |= TYPEDEF;
+ c = T_EXTERN;
+ }
+ break;
+ case RESERVED('v', 't', 8):
+ if (*ip == '(' && !strncmp(proto->tp, "va_start", 8)) c = T_VA_START;
+ break;
+ case RESERVED('v', 'd', 4):
+ if (!strncmp(proto->tp, "void", 4))
+ {
+ if (flags & (CLASSIC|PLUSONLY|INIT_DEFINE|INIT_INCLUDE)) c = T_VOID;
+ else
+ {
+ SYNC();
+ line = proto->line;
+ if (lex(proto, (flags & GLOBAL) | RECURSIVE) == '*')
+ {
+ memcopy(op - 4, "__V_", 4);
+ memcopy(ip - 4, "__V_", 4);
+ }
+ else c = T_VOID;
+ proto->line = line;
+ SYNC();
+ bp = ip;
+ }
+ }
+ break;
+ case RESERVED('w', 'e', 5):
+ if (!(flags & RECURSIVE) && !strncmp(proto->tp, "while", 5))
+ {
+ c = T_WHILE;
+ goto fsm_id;
+ }
+ break;
+ }
+#if PROTOMAIN
+ if ((flags & CLASSIC) && c != T_EXTERN)
+ c = T_ID;
+#endif
+ break;
+
+ case S_VS:
+ goto fsm_start;
+
+ case S_WS:
+ UNGETCHR();
+#if PROTOMAIN
+ if ((flags & (EXTERN|MATCH)) == EXTERN)
+ {
+ while (op > proto->ob && (*(op - 1) == ' ' || *(op - 1) == '\t'))
+ op--;
+ if (op > proto->ob && *(op - 1) != '\n') *op++ = ' ';
+ }
+#endif
+ goto fsm_start;
+
+ default:
+ if (state & SPLICE)
+ {
+ if (c == '\\')
+ {
+ if (!(n = GETCHR()))
+ {
+ goto fsm_eob;
+ fsm_splice:
+ c = '\\';
+ n = GETCHR();
+ }
+ if (n == '\n')
+ {
+ proto->line++;
+ PUTCHR('\\');
+ PUTCHR('\n');
+ bp = ip;
+ goto fsm_get;
+ }
+ UNGETCHR();
+ }
+ state &= ~SPLICE;
+ if (state >= TERMINAL)
+ goto fsm_terminal;
+ rp = fsm[state];
+ }
+ PUTCHR(c);
+ bp = ip;
+ goto fsm_get;
+ }
+ if (!(flags & (INIT_DEFINE|INIT_INCLUDE|RECURSIVE)))
+ {
+ if (!(flags & DIRECTIVE)) switch (c)
+ {
+ case '(':
+#if PROTOMAIN
+ if (!(flags & CLASSIC) || proto->brace == 0)
+#endif
+ {
+ if (paren++ == 0)
+ {
+#if PROTOMAIN
+ if (!(flags & CLASSIC) || group <= 1)
+#endif
+ {
+#if PROTOMAIN
+ args = 0;
+#endif
+ if (group++ == 0) group++;
+ else if (flags & INDIRECT) call++;
+ flags |= MATCH;
+ im = ip - 1;
+ om = op - 1;
+ }
+ sub = 0;
+ }
+ else if (paren == 2 && !aim)
+ {
+ sub++;
+ if (last == '(')
+ {
+ flags &= ~MATCH;
+ om = 0;
+ }
+ else if (flags & INDIRECT)
+ {
+ aim = ip - 1;
+ aom = op - 1;
+ }
+ else if ((flags & (MATCH|TOKENS)) == MATCH)
+ {
+ for (m = ip - 2; m > im && (*m == ' ' || *m == '\t'); m--);
+ if (m != im && sub == 1)
+ {
+ m = im + (*nns(ip) == '*');
+ }
+ if (m == im)
+ {
+ flags &= ~MATCH;
+ om = 0;
+ }
+ }
+ else if ((flags & MATCH) && sub == 1 && *nns(ip) != '*')
+ {
+ flags &= ~MATCH;
+ om = 0;
+ }
+ }
+ flags &= ~TOKENS;
+ }
+ break;
+ case ')':
+#if PROTOMAIN
+ if (!(flags & CLASSIC) || proto->brace == 0)
+#endif
+ if (--paren == 0)
+ {
+#if PROTOMAIN
+ if (flags & CLASSIC)
+ {
+ if (group != 2)
+ {
+ c = T_ID;
+ break;
+ }
+ group++;
+ }
+#endif
+ ie = ip;
+ }
+ else if (paren == 1 && (flags & INDIRECT) && !aie)
+ aie = ip;
+ break;
+ case '*':
+ if (last == '(' && group == 2)
+ {
+ group--;
+ if (paren == 1)
+ {
+ flags |= INDIRECT;
+ aim = aie = 0;
+ }
+ }
+ break;
+ case '#':
+ dir = directive(ip, dir);
+ if (proto->brace == 0 && paren == 0 && last != '=' && (flags & (CLASSIC|DECLARE|DIRECTIVE|MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS) && ((dir & DIR) != DIR_en || ((dir>>2) & DIR) != DIR_if))
+ flags |= DIRECTIVE;
+ else if (!(flags & (DECLARE|DIRECTIVE)))
+ {
+ flags |= DIRECTIVE;
+ if (!(flags & PLUSONLY))
+ {
+ bp = ip;
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip == 'l' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e')
+ {
+ if (*++ip == ' ' || *ip == '\t')
+ {
+ proto->line = 0;
+ while (*++ip >= '0' && *ip <= '9')
+ proto->line = proto->line * 10 + *ip - '0';
+ proto->line--;
+ }
+ }
+#if PROTOMAIN
+ else if ((flags & (CLASSIC|EXTERN)) == CLASSIC)
+ {
+ n = 0;
+ t = ip + 6;
+ while (ip < t && *ip >= 'a' && *ip <= 'z')
+ n = HASHKEYPART(n, *ip++);
+ switch (n)
+ {
+ case HASHKEY4('e','l','s','e'):
+ case HASHKEY5('e','n','d','i','f'):
+ while (*ip == ' ' || *ip == '\t') ip++;
+ if (*ip != '\n' && *ip != '/' && *(ip + 1) != '*')
+ {
+ flags |= JUNK|MATCH;
+ im = ip;
+ om = op + (ip - bp);
+ }
+ break;
+ case HASHKEY4('e','l','i','f'):
+ case HASHKEY5('e','r','r','o','r'):
+ case HASHKEY2('i','f'):
+ case HASHKEY5('i','f','d','e','f'):
+ case HASHKEY6('i','f','n','d','e','f'):
+ case HASHKEY5('u','n','d','e','f'):
+ break;
+ case HASHKEY6('i','n','c','l','u','d'):
+ if (*ip == 'e') ip++;
+ /*FALLTHROUGH*/
+ case HASHKEY6('d','e','f','i','n','e'):
+ case HASHKEY6('p','r','a','g','m','a'):
+ if (*ip < 'a' || *ip > 'z') break;
+ /*FALLTHROUGH*/
+ default:
+ flags |= JUNK|MATCH;
+ im = bp - 1;
+ om = op - 1;
+ break;
+ }
+ }
+ else
+#endif
+ {
+ if (*ip == 'i' && *++ip == 'n' && *++ip == 'c' && *++ip == 'l' && *++ip == 'u' && *++ip == 'd' && *++ip == 'e')
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip++ == '<' && *ip++ == 's' && *ip++ == 't' && *ip++ == 'd' && *ip++ == 'a' && *ip++ == 'r' && *ip++ == 'g' && *ip++ == '.' && *ip++ == 'h' && *ip++ == '>')
+ {
+ op = strcopy(op, "\
+if !defined(va_start)\n\
+#if defined(__STDARG__)\n\
+#include <stdarg.h>\n\
+#else\n\
+#include <varargs.h>\n\
+#endif\n\
+#endif\n\
+");
+ op = linesync(proto, op, proto->line);
+ break;
+ }
+ }
+ else if (*ip == 'd' && *++ip == 'e' && *++ ip == 'f' && *++ip == 'i' && *++ip == 'n' && *++ip == 'e' && (*++ip == ' ' || *ip == '\t'))
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t'))
+ {
+ t = ip;
+ while (*++t == ' ' || *t == '\t');
+ if (*t == 'e' && *++t == 'x' && *++ t == 't' && *++t == 'e' && *++t == 'r' && *++t == 'n' && (*++t == ' ' || *t == '\t' || *t == '\n' || *t == '\r'))
+ ip = t;
+ t = ip;
+ while (*++t == ' ' || *t == '\t');
+ if (*t == '_' && *(t + 1) == '_')
+ {
+ op = strcopy(op, "undef __MANGLE__\n");
+ op = linesync(proto, op, proto->line);
+ op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
+ break;
+ }
+ }
+ flags |= DEFINE|MATCH;
+ im = bp - 1;
+ om = op - 1;
+ }
+ else if (*ip == 'u' && *++ip == 'n' && *++ ip == 'd' && *++ip == 'e' && *++ip == 'f' && (*++ip == ' ' || *ip == '\t'))
+ {
+ while (*++ip == ' ' || *ip == '\t');
+ if (*ip == 'e' && *++ip == 'x' && *++ ip == 't' && *++ip == 'e' && *++ip == 'r' && *++ip == 'n' && (*++ip == ' ' || *ip == '\t' || *ip == '\n' || *ip == '\r'))
+ {
+ op = strcopy(op, "undef __MANGLE__\n");
+ op = linesync(proto, op, proto->line);
+ op = strcopy(op, "#define __MANGLE__ __LINKAGE__");
+ break;
+ }
+ flags |= DEFINE|MATCH;
+ im = bp - 1;
+ om = op - 1;
+ }
+ }
+ ip = bp;
+ }
+ break;
+ }
+ else
+ break;
+ /*FALLTHROUGH*/
+ case '{':
+ if (proto->brace++ == 0 && paren == 0)
+ {
+ if (last == '=') flags |= INIT;
+#if PROTOMAIN
+ else if (flags & CLASSIC)
+ {
+ if ((flags & (MATCH|OTHER|SKIP)) == MATCH)
+ {
+ if (args)
+ {
+ v = number(op, args < 0 ? -args : args);
+ v = strcopy(v, " argument actual/formal mismatch");
+ *v++ = ' ';
+ v = memcopy(v, im, ie - im);
+ *v = 0;
+ proto_error((char*)proto + sizeof(struct proto), 2, op, NiL);
+ }
+ ip--;
+ /*UNDENT...*/
+ v = ie;
+ while (ie < ip)
+ if (*ie++ == '/' && *ie == '*')
+ {
+ e = ie - 1;
+ while (++ie < ip)
+ {
+ if (*ie == '*')
+ {
+ while (ie < ip && *ie == '*') ie++;
+ if (ie < ip && *ie == '/')
+ {
+ while (++ie < ip && (*ie == ' ' || *ie == '\t'));
+ while (e > v && (*(e - 1) == ' ' || *(e - 1) == '\t')) e--;
+ if (e > v && *e != '\n') *e++ = ' ';
+ t = ie;
+ while (--e >= v)
+ *--t = *e;
+ v = t;
+ break;
+ }
+ }
+ }
+ }
+ ie = v;
+ /*...INDENT*/
+ op = om++;
+ if (flags & EXTERN)
+ {
+ v = op;
+ while (v > ko && *--v != ' ');
+ if (*v != ' ')
+ {
+ om = (v = (op += 4)) + 1;
+ while (v >= ko + 4)
+ {
+ *v = *(v - 4);
+ v--;
+ }
+ memcopy(ko, "int ", 4);
+ }
+ if (*v == ' ')
+ {
+ while (*(v + 1) == '*')
+ *v++ = '*';
+ *v = '\t';
+ if ((v - ko) <= 8)
+ {
+ om = (e = ++op) + 1;
+ while (e > v)
+ {
+ *e = *(e - 1);
+ e--;
+ }
+ }
+ }
+ om = (v = (op += 7)) + 1;
+ while (v >= ko + 7)
+ {
+ *v = *(v - 7);
+ v--;
+ }
+ memcopy(ko, "extern ", 7);
+ }
+ PUTCHR('(');
+ t = op;
+ e = 0;
+ /*UNDENT...*/
+ while (ie < ip)
+ {
+ if ((c = *ie) == ' ' || c == '\t' || c == '\n')
+ {
+ while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
+ if (ie >= ip) break;
+ if (c != '*' && op > om) PUTCHR(' ');
+ }
+ if ((n = ((c = *ie) == ',')) || c == ';')
+ {
+ if (flags & EXTERN)
+ {
+ m = op;
+ while (op > om && ((c = *(op - 1)) == '(' || c == ')' || c == '[' || c == ']'))
+ op--;
+ v = op;
+ while (op > om && (c = *(op - 1)) != ' ' && c != '*')
+ op--;
+ while (*(op - 1) == ' ')
+ op--;
+ if (!e)
+ {
+ e = op;
+ while (e > om && *(e - 1) == '*')
+ e--;
+ }
+#if _s5r4_386_compiler_bug_fixed_
+ if (op <= om || *(op - 1) == ',' && (*op++ = ' '))
+ op = strcopy(op, "int");
+#else
+ if (op <= om)
+ op = strcopy(op, "int");
+ else if (*(op - 1) == ',')
+ op = strcopy(op, " int");
+#endif
+ while (v < m)
+ PUTCHR(*v++);
+ }
+ PUTCHR(',');
+ if (n)
+ {
+ if (x = !e) e = op - 1;
+ PUTCHR(' ');
+ m = t;
+ while (m < e)
+ PUTCHR(*m++);
+ if (x)
+ {
+ m = e;
+ while (*--e != ' ');
+ while (*(e - 1) == '*') e--;
+ op -= m - e;
+ }
+ }
+ while ((c = *++ie) == ' ' || c == '\t' || c == '\n');
+ if (ie >= ip) UNPUTCHR();
+ else PUTCHR(' ');
+ if (!n)
+ {
+ t = op;
+ e = 0;
+ }
+ }
+ else if (*ie == '*')
+ {
+ if (op > om && (c = *(op - 1)) == ' ') op--;
+ while (*ie == '*') PUTCHR(*ie++);
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ if (c != '(') PUTCHR(' ');
+ }
+ else if (*ie == '(')
+ {
+ if (op > om && *(op - 1) == ' ') op--;
+ PUTCHR(*ie++);
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ }
+ else if (*ie == ')')
+ {
+ if (op > om && *(op - 1) == '(')
+ proto_error((char*)proto + sizeof(struct proto), 1, "function pointer argument prototype omitted", NiL);
+ PUTCHR(*ie++);
+ while (*ie == ' ' || *ie == '\t' || *ie == '\n') ie++;
+ }
+ else if ((flags & EXTERN) && (op == om || *(op - 1) == ' ') && *ie == 'r' && !strncmp(ie, "register", 8) && (*(ie + 8) == ' ' || *(ie + 8) == '\t' || *(ie + 8) == '\n'))
+ {
+ ie += 8;
+ if (op > om) UNPUTCHR();
+ }
+ else PUTCHR(*ie++);
+ }
+ /*...INDENT*/
+ if (op <= om) op = strcopy(op, "void");
+ PUTCHR(')');
+ if (flags & EXTERN)
+ {
+ PUTCHR(';');
+ PUTCHR('\n');
+ SYNCOUT();
+ KEEPOUT();
+ }
+ else
+ {
+ PUTCHR('\n');
+ PUTCHR(*ip);
+ }
+ ip++;
+ flags &= ~(MATCH|SKIP);
+ }
+ }
+#endif
+ else if ((flags & (MATCH|PLUSONLY|SKIP|TOKENS)) == (MATCH|TOKENS))
+ {
+ line = proto->line;
+ op = strcopy(om, " __PARAM__(");
+ op = memcopy(op, im, ie - im);
+ PUTCHR(',');
+ PUTCHR(' ');
+ PUTCHR('(');
+ flags &= ~(MATCH|SKIP);
+ if (flags & VARIADIC)
+ {
+ if ((vc = ie - im + 1) > sizeof(proto->variadic)) vc = sizeof(proto->variadic);
+ memcopy(proto->variadic, im, vc);
+ op = strcopy(op, "va_alist)) __OTORP__(va_dcl)\n{");
+ }
+ else
+ {
+ flags |= SKIP;
+ proto->ip = im;
+ proto->op = op;
+ group = 0;
+ brack = 0;
+ for (;;)
+ {
+ switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
+ {
+ case '[':
+ brack++;
+ continue;
+ case ']':
+ brack--;
+ continue;
+ case '(':
+ if (paren++) group++;
+ continue;
+ case ')':
+ if (--paren == 0)
+ {
+ group = 0;
+ if (flags & MATCH)
+ {
+ flags &= ~(MATCH|SKIP);
+ op = memcopy(op, m, e - m);
+ }
+ break;
+ }
+ continue;
+ case ',':
+ if (paren == 1)
+ {
+ group = 0;
+ if (flags & MATCH)
+ {
+ flags &= ~(MATCH|SKIP);
+ op = memcopy(op, m, e - m);
+ }
+ PUTCHR(',');
+ PUTCHR(' ');
+ proto->op = op;
+ }
+ continue;
+ case T_ID:
+ if (group <= 1 && !brack)
+ {
+ flags |= MATCH;
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ PUTCHR(')');
+ PUTCHR(')');
+ }
+ if (!(flags & SKIP))
+ {
+ flags |= SKIP;
+ proto->op = strcopy(op, " __OTORP__(");
+ proto->ip = im + 1;
+ n = *(ie - 1);
+ *(ie - 1) = ';';
+ c = *ie;
+ *ie = 0;
+ lex(proto, (flags & GLOBAL) | DECLARE);
+ *(ie - 1) = n;
+ *ie = c;
+ proto->ip = ie;
+ op = proto->op;
+ PUTCHR(')');
+ }
+ if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
+ op = linesync(proto, op, proto->line = line);
+ if (flags & DIRECTIVE)
+ {
+ proto->brace = 0;
+ PUTCHR('\n');
+ PUTCHR('#');
+ }
+ else if (!(flags & VARIADIC)) PUTCHR('{');
+ }
+ }
+ flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
+ call = 0;
+ group = 0;
+ break;
+ case '}':
+ flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP|TOKENS);
+ if (--proto->brace == 0)
+ {
+ flags &= ~(INIT|VARIADIC|VARIADIC2);
+#if PROTOMAIN
+ if (flags & EXTERN) BACKOUT();
+#endif
+ }
+ call = 0;
+ group = 0;
+ paren = 0;
+ break;
+ case '=':
+ if (last == '?') flags |= DIRECTIVE;
+ else if (paren == 0 && (flags & (INIT|MATCH|SKIP)) == MATCH) goto fsm_statement;
+ goto fsm_other;
+ case ',':
+#if PROTOMAIN
+ if (flags & CLASSIC)
+ {
+ if (paren == 1) args++;
+ else
+ {
+ args--;
+ flags &= ~MATCH;
+ }
+ break;
+ }
+#endif
+ if (paren == 0 && (flags & DECLARE)) *(op - 1) = c = ';';
+ /*FALLTHROUGH*/
+ case ';':
+ fsm_statement:
+ if (flags & INIT) /* ignore */;
+#if PROTOMAIN
+ else if (flags & CLASSIC)
+ {
+ if (paren == 0)
+ {
+ if ((flags & MATCH) && last == ')')
+ flags &= ~MATCH;
+ if (!(flags & MATCH))
+ {
+ call = 0;
+ group = 0;
+ flags &= ~SKIP;
+ if (flags & EXTERN) BACKOUT();
+ if (flags & SLIDE)
+ {
+ SYNC();
+ return 0;
+ }
+ }
+ else
+ {
+ args--;
+ if ((flags & (EXTERN|SKIP)) == (EXTERN|SKIP))
+ BACKOUT();
+ }
+ }
+ }
+#endif
+ else if (paren == 0)
+ {
+ if ((flags & (MATCH|OTHER|SKIP)) == MATCH && call > 1)
+ {
+ if ((flags & MANGLE) && func)
+ {
+ func[0] = 'F';
+ func[1] = 'U';
+ func[2] = 'N';
+ func[3] = 'C';
+ func = 0;
+ }
+ if ((flags & (DECLARE|INDIRECT)) == INDIRECT && aim && aie < im)
+ {
+ while (aie < ip && (*aie == ' ' || *aie == '\t' || *aie == '\n')) aie++;
+ v = aim;
+ while (v < aie)
+ if (*v++ == ')') break;
+ while (v < aie && (*v == ' ' || *v == '\t' || *v == '\n')) v++;
+ if (v == aie || !(flags & PLUSPLUS))
+ {
+ if (flags & PLUSPLUS) n = 3;
+ else if (v == aie && *v == '(') n = 10;
+ else n = 11;
+ ko = op;
+ om += n;
+ v = op += n;
+ while (v >= ko + n)
+ {
+ *v = *(v - n);
+ v--;
+ }
+ if (flags & PLUSPLUS) memcopy(aom, "(...))", 6);
+ else if (n == 10) memcopy(aom, "(__VARARG__))", 13);
+ else
+ {
+ ko = strcopy(aom, " __PROTO__(");
+ ko = memcopy(ko, aim, aie - aim);
+ *ko = ')';
+ if (++ko >= om)
+ {
+ *ko++ = ')';
+ om = ko;
+ }
+ }
+ }
+ }
+ else if (flags & TYPEDEF)
+ {
+ op = om;
+ while (*--op == ' ' || *op == '\t' || *op == '\n');
+ if (*op != ')')
+ {
+ op = om += 14;
+ *--op = ')';
+ while ((x = *(op - 14)) >= 'A' && x <= 'Z' || x >= 'a' && x <= 'z' || x >= '0' && x <= '9' || x == '_')
+ *--op = x;
+ memcopy(op - 13, "(__OTORP__(*)", 13);
+ }
+ }
+ if (flags & OTHER)
+ ;
+ else if (flags & PLUSPLUS)
+ {
+ op = om;
+ if (!(flags & TOKENS)) op = strcopy(op, "(...)");
+ else op = memcopy(op, im, ie - im);
+ PUTCHR(c);
+ }
+ else
+ {
+ if (flags & DECLARE) op = strcopy(om, "()");
+ else if (!(flags & TOKENS)) op = strcopy(om, "(__VARARG__)");
+ else
+ {
+ op = strcopy(om, " __PROTO__(");
+ op = memcopy(op, im, ie - im);
+ PUTCHR(')');
+ }
+ if (flags & EXTERNALIZE) memcpy(proto->ox, "extern", 6);
+ PUTCHR(c);
+ }
+ flags &= ~(MATCH|VARIADIC|VARIADIC2);
+ if (c == ',' && !(flags & INDIRECT))
+ {
+ call = 1;
+ group = 0;
+ break;
+ }
+ }
+ else if (flags & (OTHER|SKIP)) call = 0;
+ if (c == ';')
+ {
+ flags &= ~(EXTERNALIZE|MANGLE|TOKENS|TYPEDEF);
+ call = 0;
+ if (flags & SLIDE)
+ {
+ SYNC();
+ return 0;
+ }
+ }
+ else call = call > 1 && c == ',';
+ group = 0;
+ flags &= ~(IDID|INDIRECT|MATCH|OTHER|SKIP);
+ }
+ else if (paren == 1 && group == 1 && !(flags & (IDID|MANGLE))) flags |= TOKENS|OTHER;
+ break;
+ case T_DO:
+ case T_IF:
+ flags |= TOKENS|SKIP;
+ break;
+ case T_EXTERN:
+#if PROTOMAIN
+ if (flags & CLASSIC)
+ {
+ if (proto->brace == 0)
+ flags |= SKIP;
+ }
+ else
+#endif
+ if (paren == 0 && !(flags & TYPEDEF))
+ {
+ flags |= MANGLE;
+ if (!(flags & PLUSONLY) || proto->package)
+ {
+ op = strcopy(op, " __MANGLE__");
+ if (proto->package)
+ {
+ op = strcopy(op - 1, proto->package);
+ func = op + 1;
+ op = strcopy(op, "_DATA__");
+ }
+ }
+ else
+ func = 0;
+ }
+ break;
+ case T_VARIADIC:
+ if (paren == 0 && (flags & (DECLARE|VARIADIC)) == DECLARE)
+ {
+ op -= 3;
+ SYNC();
+ return c;
+ }
+ if (paren == 1 && !(flags & SKIP))
+ flags |= VARIADIC;
+ flags |= TOKENS;
+ break;
+ case T_VOID:
+ goto fsm_id;
+ case T_VA_START:
+ if ((flags & (PLUSONLY|VARIADIC)) == VARIADIC)
+ {
+ flags &= ~MATCH;
+ line = proto->line;
+ op = strcopy(op - 8, "__VA_START__");
+ SYNC();
+ for (;;)
+ {
+ switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
+ {
+ case 0:
+ case ';':
+ break;
+ case T_ID:
+ if (!(flags & MATCH))
+ {
+ flags |= MATCH;
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ CACHE();
+ if (flags & MATCH)
+ {
+ v = m;
+ n = e - m;
+ }
+ else
+ {
+ v = "ap";
+ n = 2;
+ }
+ op = strcopy(op, " __OTORP__(");
+ proto->ip = proto->variadic;
+ proto->op = op;
+ flags &= ~MATCH;
+ group = 0;
+ bp = proto->ip + 1;
+ if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
+ for (;;)
+ {
+ switch (lex(proto, (flags & GLOBAL) | RECURSIVE))
+ {
+ case '(':
+ if (paren++) group++;
+ continue;
+ case ')':
+ if (--paren == 0)
+ {
+ if (flags & MATCH)
+ {
+ flags &= ~MATCH;
+ if (!(flags & VARIADIC2))
+ {
+ op = memcopy(op, m, e - m);
+ op = strcopy(op, " = ");
+ }
+ op = strcopy(op, "va_arg(");
+ op = memcopy(op, v, n);
+ PUTCHR(',');
+ PUTCHR(' ');
+ if (m > bp) op = memcopy(op, bp, m - bp);
+ else op = strcopy(op, "int ");
+ if (group > 1) op = strcopy(op, ")()");
+ else op = memcopy(op, e, proto->ip - e - 1);
+ PUTCHR(')');
+ PUTCHR(';');
+ }
+ group = 0;
+ break;
+ }
+ continue;
+ case ',':
+ if (paren == 1)
+ {
+ if (flags & MATCH)
+ {
+ flags &= ~MATCH;
+ if (!(flags & VARIADIC2))
+ {
+ op = memcopy(op, m, e - m);
+ op = strcopy(op, " = ");
+ }
+ op = strcopy(op, "va_arg(");
+ op = memcopy(op, v, n);
+ PUTCHR(',');
+ PUTCHR(' ');
+ if (m > bp) op = memcopy(op, bp, m - bp);
+ else op = strcopy(op, "int ");
+ if (group > 1) op = strcopy(op, ")()");
+ else op = memcopy(op, e, proto->ip - e - 1);
+ PUTCHR(')');
+ PUTCHR(';');
+ bp = proto->ip + 1;
+ if (*bp == 'r' && !strncmp(bp, "register", 8) && (*(bp + 8) == ' ' || *(bp + 8) == '\t')) bp += 9;
+ }
+ group = 0;
+ proto->op = op;
+ }
+ continue;
+ case T_ID:
+ if (group <= 1)
+ {
+ flags |= MATCH;
+ m = proto->tp;
+ e = proto->ip;
+ }
+ continue;
+ default:
+ continue;
+ }
+ break;
+ }
+ op = strcopy(op, ")");
+ flags |= VARIADIC2;
+ proto->line = line;
+ call = 0;
+ break;
+ }
+ /*FALLTHROUGH*/
+ case T_ID:
+ fsm_id:
+#if PROTOMAIN
+ if (flags & CLASSIC)
+ {
+ if (!args && paren == 1) args++;
+ break;
+ }
+#endif
+ if (paren == 0)
+ {
+ if (last == ')')
+ {
+ if (proto->brace == 0 && !(flags & DECLARE)) flags |= SKIP;
+ call = !call;
+ }
+ else if ((flags & SKIP) || c == T_ID || c == T_VOID) call++;
+ else flags |= SKIP;
+ if (last == T_ID) flags |= IDID;
+ }
+ c = T_ID;
+ flags |= TOKENS;
+ break;
+ case T_INVALID:
+ if (*proto->tp >= '0' && *proto->tp <= '9')
+ {
+ n = 0;
+ for (;; op--)
+ {
+ switch (*(op - 1))
+ {
+ case 'f':
+ case 'F':
+ t = op;
+ while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+ if (*t == '.')
+ op--;
+ n = 0;
+ break;
+ case 'l':
+ case 'L':
+ if (!(n & 01))
+ {
+ n |= 01;
+ t = op;
+ while ((c = *--t) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z');
+ if (*t == '.')
+ {
+ n = 0;
+ op--;
+ break;
+ }
+ }
+ continue;
+ case 'u':
+ case 'U':
+ n |= 02;
+ continue;
+ }
+ break;
+ }
+ if (n & 01)
+ *op++ = 'L';
+ if (n & 02)
+ {
+ m = op;
+ t = op = m + 10;
+ while ((c = *--m) >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
+ *--t = c;
+ c = *t;
+ strcopy(m + 1, "(unsigned)");
+ *t = c;
+ break;
+ }
+ }
+ goto fsm_other;
+#if PROTOMAIN
+ case '[':
+ if ((flags & CLASSIC) && paren == 0 && group <= 2) flags |= SKIP;
+ /*FALLTHROUGH*/
+#endif
+ default:
+ fsm_other:
+#if PROTOMAIN
+ if (flags & CLASSIC) break;
+#endif
+ flags |= TOKENS;
+ if (paren == 0) flags |= OTHER;
+ break;
+ }
+ else if (c == '#' && *ip != '(') flags |= SHARP;
+ last = c;
+#if PROTOMAIN
+ if ((flags & (EXTERN|MATCH)) == (EXTERN|MATCH) && ((flags & (DIRECTIVE|SKIP)) || proto->brace || c != '(' && c != ')' && c != '*' && c != T_ID))
+ CACHEOUT();
+ else
+#endif
+ SYNCOUT();
+ goto fsm_start;
+ }
+ else if (flags & (INIT_DEFINE|INIT_INCLUDE))
+ {
+#if PROTOMAIN
+ if ((flags & YACC) && c == '%' && *ip == '{') t = 0;
+ else
+#endif
+ {
+ if (c == '#') for (t = ip; *t == ' ' || *t == '\t'; t++);
+ else t = "";
+ if (*t++ == 'i' && *t++ == 'f' && *t++ == 'n' && *t++ == 'd' && *t++ == 'e' && *t++ == 'f')
+ {
+#if !PROTOMAIN
+ while (*t == ' ' || *t == '\t') t++;
+ if (*t != '_')
+#endif
+ t = 0;
+ }
+ }
+ if (t)
+ {
+ ip = bp;
+ op = proto->op;
+ }
+ else while (*ip != '\n') *op++ = *ip++;
+ op = init(proto, op, flags);
+ op = linesync(proto, op, proto->line);
+ flags &= ~(INIT_DEFINE|INIT_INCLUDE);
+ proto->flags &= ~(INIT_DEFINE|INIT_INCLUDE);
+ goto fsm_start;
+ }
+ SYNC();
+ return c;
+}
+
+/*
+ * close a proto buffer stream
+ */
+
+void
+pppclose(char* iob)
+{
+ register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
+
+ if (proto->flags & MORE) close(proto->fd);
+ free((char*)proto); /* some ANSI cc's botch the free() prototype */
+}
+
+/*
+ * open a new proto buffer stream
+ * read buffer pointer returned
+ * 0 returned on error or if no magic
+ *
+ * file !=0 file path to open, otherwise use fd
+ * fd open file fd if file==0
+ * notice !=0 copyright notice info commented at the top
+ * options !=0 additional notice name=value pairs, space or ; separated
+ * package !=0 generate header for this package
+ */
+
+char*
+pppopen(char* file, int fd, char* notice, char* options, char* package, char* comment, int flags)
+{
+ register struct proto* proto;
+ register char* iob;
+ register long n;
+ register char* s;
+ int pragma;
+ char* b;
+#if PROTOMAIN
+ int comlen;
+ char com[80];
+#endif
+ int m = 0;
+
+ static int retain;
+
+ /*
+ * initialize proto
+ */
+
+#if PROTOMAIN
+ if (flags & PROTO_CLASSIC) flags &= ~PROTO_INCLUDE;
+#endif
+ if (flags & PROTO_RETAIN) flags &= ~retain;
+ else retain &= PROTO_INITIALIZED;
+ if (file && (fd = open(file, O_RDONLY)) < 0) return 0;
+#if !PROTOMAIN
+ if ((n = lseek(fd, 0L, 2)) > 0)
+ {
+ if (lseek(fd, 0L, 0)) return 0;
+ if (n < CHUNK) n = CHUNK;
+ else if (n > 2 * BLOCK) n = 0;
+ m = 1;
+ }
+ if (n > 0)
+ {
+ /*
+ * file read in one chunk
+ */
+
+ if (!(proto = newof(0, struct proto, 1, 4 * n + 2)))
+ return 0;
+ proto->iz = n;
+ proto->oz = 3 * n;
+ n = 0;
+ }
+ else
+#endif
+ {
+ /*
+ * file read in BLOCK chunks
+ */
+
+ n = BLOCK;
+ if (!(proto = newof(0, struct proto, 1, 5 * n + 2)))
+ return 0;
+ proto->iz = n;
+ proto->oz = 3 * n;
+ proto->flags |= MORE;
+ }
+ proto->fd = fd;
+ proto->package = package;
+ iob = (char*)proto + sizeof(struct proto);
+ proto->op = proto->ob = iob;
+ proto->ip = proto->ib = iob + proto->oz + n;
+ if (m) proto->options |= REGULAR;
+ if (!comment)
+ comment = "/*";
+ if (!(proto->cc[0] = comment[0]))
+ notice = options = 0;
+ else if (comment[1])
+ {
+ proto->cc[1] = comment[1];
+ proto->cc[2] = comment[2] ? comment[2] : comment[0];
+ }
+ else
+ proto->cc[1] = proto->cc[2] = comment[0];
+
+ /*
+ * read the first chunk
+ */
+
+ n = read(fd, proto->ip, proto->iz);
+ if (!(proto->flags & MORE))
+ close(fd);
+ if (n < 0)
+ {
+ pppclose(iob);
+ return 0;
+ }
+ *(proto->ip + n) = 0;
+
+ /*
+ * check for proto pragma in first block of lines
+ * pragma blanked out if found
+ *
+ * -1 no pragma
+ * 0 #pragma noprototyped
+ * 1 #pragma prototyped
+ *
+ * NOTE: matches may occur inside comments and quotes
+ */
+
+#if PROTOMAIN
+ if (!notice && !options || (comlen = astlicense(com, sizeof(com), NiL, "type=check", proto->cc[0], proto->cc[1], proto->cc[2])) <= 0)
+ *com = 0;
+#endif
+ pragma = -1;
+ s = proto->ip;
+ m = MAGICTOP;
+ while (m-- > 0 && *s)
+ {
+ while (*s == ' ' || *s == '\t') s++;
+ if (*s == '#')
+ {
+ b = s++;
+ while (*s == ' ' || *s == '\t') s++;
+ if (!strncmp(s, MAGICDIR, sizeof(MAGICDIR) - 1) && (*(s += sizeof(MAGICDIR) - 1) == ' ' || *s == '\t'))
+ {
+ while (*s == ' ' || *s == '\t') s++;
+ if (*s == 'n' && *(s + 1) == 'o')
+ {
+ s += 2;
+ pragma = -2;
+ }
+ if (!strncmp(s, MAGICARG, sizeof(MAGICARG) - 1) && (*(s += sizeof(MAGICARG) - 1) == ' ' || *s == '\t' || *s == '\n' || *s == '\r'))
+ while (*s)
+ {
+ if ((*(s - 1) == ' ' || *(s - 1) == '\t') && *s == *MAGICOFF && !strncmp(s, MAGICOFF, sizeof(MAGICOFF) - 1))
+ notice = options = 0;
+ if (*s++ == '\n')
+ {
+ pragma += 2;
+#if PROTOMAIN
+ if (!(flags & PROTO_DISABLE) || (flags & PROTO_NOPRAGMA))
+#endif
+ for (s--; b < s; *b++ = ' ');
+ goto magic;
+ }
+ }
+ pragma = -1;
+ }
+ }
+ else if (*s == '/' && !strncmp(s, MAGICGEN, sizeof(MAGICGEN) - 1))
+ {
+ pragma = 0;
+ break;
+ }
+#if PROTOMAIN
+ else if (*s == '%' && *(s + 1) == '{')
+ proto->flags |= YACC;
+ if (notice || options)
+ {
+ if (*s == *com && !strncmp(s, com, comlen))
+ notice = options = 0;
+ else
+ while (*s)
+ {
+ if (*s == *NOTICED && !strncmp(s, NOTICED, sizeof(NOTICED) - 1))
+ {
+ s += sizeof(NOTICED) - 1;
+ while (*s == ' ' || *s == '\t')
+ s++;
+ if (*s == '(' && (*(s + 1) == 'c' || *(s + 1) == 'C') && *(s + 2) == ')' || *s >= '0' && *s <= '9' && *(s + 1) >= '0' && *(s + 1) <= '9')
+ {
+ notice = options = 0;
+ break;
+ }
+ }
+ else if (*s++ == '\n')
+ {
+ s--;
+ break;
+ }
+ }
+ }
+#endif
+ while (*s && *s++ != '\n');
+ }
+ magic:
+ if (flags & PROTO_PLUSPLUS) proto->flags |= PLUSPLUS;
+ if (flags & PROTO_TEST) proto->test = 1;
+ if (flags & PROTO_EXTERNALIZE) proto->options |= EXTERNALIZE;
+#if PROTOMAIN
+ if (flags & PROTO_CLASSIC) pragma = -pragma;
+ if (flags & PROTO_DISABLE) pragma = 0;
+ if (flags & PROTO_LINESYNC) proto->flags |= LINESYNC;
+ if (!(proto->flags & YACC) && file && (m = strlen(file)) > 2 && file[--m] == 'y' && file[--m] == '.')
+ proto->flags |= YACC;
+#endif
+ if (pragma <= 0)
+ {
+ if (flags & PROTO_PLUSPLUS)
+ {
+ flags &= ~(PROTO_HEADER|PROTO_INCLUDE);
+ proto->flags |= PLUSONLY;
+ }
+ else if (!(flags & (PROTO_FORCE|PROTO_PASS)))
+ {
+ pppclose(iob);
+ return 0;
+ }
+ else if ((flags & (PROTO_FORCE|PROTO_PASS)) == PROTO_PASS || !pragma)
+ {
+ proto->flags |= PASS;
+ if (proto->flags & MORE)
+ proto->oz += proto->iz;
+ proto->iz = n;
+ if (notice || options)
+ {
+ if (proto->cc[0] == '#' && proto->ip[0] == '#' && proto->ip[1] == '!')
+ {
+ s = proto->ip;
+ while (*s && *s++ != '\n');
+ m = s - proto->ip;
+ proto->op = memcopy(proto->op, proto->ip, m);
+ proto->ip = s;
+ proto->iz = n -= m;
+ }
+#if PROTOMAIN
+ if (proto->cc[0])
+ {
+ if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
+ proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
+ else
+ proto->op += comlen;
+ }
+ if (!(flags & PROTO_CLASSIC) && !(proto->flags & YACC))
+#endif
+ proto->op = linesync(proto, proto->op, 1);
+ proto->iz += proto->op - proto->ob;
+ }
+ memcopy(proto->op, proto->ip, n);
+ return iob;
+ }
+ }
+#if PROTOMAIN
+ if (!(retain & PROTO_INITIALIZED))
+ {
+ retain |= PROTO_INITIALIZED;
+ ppfsm(FSM_INIT, NiL);
+ }
+#endif
+ proto->line = 1;
+#if CHUNK >= 512
+ if (notice || options || (flags & (PROTO_HEADER|PROTO_INCLUDE)))
+ {
+#if PROTOMAIN
+ if (notice || options)
+ {
+ if ((comlen = astlicense(proto->op, proto->oz, notice, options, proto->cc[0], proto->cc[1], proto->cc[2])) < 0)
+ proto_error((char*)proto + sizeof(struct proto), 1, proto->op, NiL);
+ else
+ proto->op += comlen;
+ }
+#endif
+ if (flags & PROTO_INCLUDE)
+ {
+ proto->flags |= INIT_INCLUDE;
+ if (flags & PROTO_RETAIN)
+ retain |= PROTO_INCLUDE;
+ }
+ else if (flags & PROTO_HEADER)
+ {
+ if (flags & PROTO_RETAIN) retain |= PROTO_HEADER;
+#if PROTOMAIN
+ if (flags & PROTO_CLASSIC)
+ {
+ *proto->op++ = '#';
+ proto->op = strcopy(proto->op, MAGICDIR);
+ *proto->op++ = ' ';
+ proto->op = strcopy(proto->op, MAGICARG);
+ *proto->op++ = '\n';
+ }
+ else
+#endif
+ proto->flags |= INIT_DEFINE;
+ }
+#if PROTOMAIN
+ if (!(flags & PROTO_CLASSIC))
+ {
+ if (proto->flags & YACC)
+ {
+ proto->op = strcopy(proto->op, "\n%{\n" + !notice);
+ proto->op = strcopy(proto->op, MAGICGEN);
+ proto->op = strcopy(proto->op, "%}\n");
+ }
+ else
+ {
+ if (n || notice || options)
+ *proto->op++ = '\n';
+ proto->op = strcopy(proto->op, MAGICGEN);
+ if (n)
+ proto->op = linesync(proto, proto->op, proto->line);
+ else if (proto->flags & (INIT_DEFINE|INIT_INCLUDE))
+ proto->op = init(proto, proto->op, proto->flags);
+ }
+ }
+#endif
+ }
+#endif
+#if PROTOMAIN
+ proto->file = file;
+ if (flags & PROTO_CLASSIC)
+ {
+ proto->flags |= CLASSIC;
+ if (!(flags & PROTO_HEADER)) proto->flags |= EXTERN;
+ }
+#endif
+ return iob;
+}
+
+/*
+ * read next proto'd chunk into iob
+ * the chunk is 0 terminated and its size is returned
+ */
+
+int
+pppread(char* iob)
+{
+ register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
+ register int n;
+
+ if (proto->flags & PASS)
+ {
+ if (proto->iz)
+ {
+ n = proto->iz;
+ proto->iz = 0;
+ }
+ else if (!(proto->flags & MORE)) n = 0;
+ else if ((n = read(proto->fd, proto->ob, proto->oz)) <= 0 || (proto->options & REGULAR) && n < proto->oz)
+ {
+ proto->flags &= ~MORE;
+ close(proto->fd);
+ }
+ }
+ else
+ {
+ if (proto->op == proto->ob)
+ {
+ if (proto->flags & ERROR) return -1;
+#if PROTOMAIN
+ if (proto->flags & YACC)
+ {
+ register char* ip = proto->ip;
+ register char* op = proto->ob;
+ register char* ep = proto->ob + proto->oz - 2;
+
+ if (!*ip)
+ {
+ ip = proto->ip = proto->ib;
+ if (!(proto->flags & MORE)) n = 0;
+ else if ((n = read(proto->fd, ip, proto->iz)) <= 0 || (proto->options & REGULAR) && n < proto->iz)
+ {
+ if (n < 0) n = 0;
+ proto->flags &= ~MORE;
+ close(proto->fd);
+ }
+ ip[n] = 0;
+ }
+ if (proto->flags & YACCSPLIT)
+ {
+ proto->flags &= ~YACCSPLIT;
+ if (*ip == '%')
+ {
+ *op++ = *ip++;
+ if (proto->flags & YACC2) proto->flags &= ~YACC;
+ else proto->flags |= YACC2;
+ }
+ }
+ if (proto->flags & YACC)
+ while (op < ep && (n = *op++ = *ip))
+ {
+ ip++;
+ if (n == '%')
+ {
+ if (*ip == '%' && (ip == proto->ip + 1 || *(ip - 2) == '\n'))
+ {
+ *op++ = *ip++;
+ if (proto->flags & YACC2) proto->flags &= ~YACC;
+ else proto->flags |= YACC2;
+ break;
+ }
+ if (!*ip)
+ {
+ *op++ = '%';
+ proto->flags |= YACCSPLIT;
+ break;
+ }
+ }
+ else if (n == '\n') proto->line++;
+ }
+ proto->op = memcopy(proto->ob, proto->ip, ip - proto->ip);
+ proto->ip = ip;
+ }
+ else
+#endif
+ lex(proto, proto->flags);
+ if ((proto->flags & (ERROR|MORE)) == ERROR)
+ proto->op = strcopy(proto->op, "/* NOTE: some constructs may not have been converted */\n");
+ }
+ n = proto->op - proto->ob;
+ proto->op = proto->ob;
+ }
+ return n;
+}
+
+#if !PROTOMAIN
+
+/*
+ * drop control of iob after first pppread()
+ * return value is input fd
+ * if fd<0 then all data in iob
+ */
+
+int
+pppdrop(char* iob)
+{
+ register struct proto* proto = (struct proto*)(iob - sizeof(struct proto));
+
+ if (proto->flags & MORE)
+ {
+ proto->flags &= ~MORE;
+ return proto->fd;
+ }
+ return -1;
+}
+
+#endif
diff --git a/usr/src/lib/libpp/common/ppsearch.c b/usr/src/lib/libpp/common/ppsearch.c
new file mode 100644
index 0000000000..f9bf29fe01
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppsearch.c
@@ -0,0 +1,807 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * include file search support
+ */
+
+#include "pplib.h"
+
+#define SEARCH_NEXT (SEARCH_USER<<1)/* search for next (uncover) */
+#define SEARCH_SKIP (SEARCH_USER<<2)/* current binding skipped */
+#define SEARCH_TEST (SEARCH_USER<<3)/* test for binding */
+#define SEARCH_FOUND (SEARCH_USER<<4)/* current binding found */
+
+#define COLUMN_TAB 7
+#define COLUMN_MAX 72
+
+#if ARCHIVE
+
+#include <vdb.h>
+#include <ls.h>
+
+#endif
+
+/*
+ * multiple include test
+ * fp is a canonicalized ppfile pointer
+ *
+ * test
+ *
+ * INC_CLEAR can be included again
+ * INC_TEST test if include required
+ * <symbol> ifndef guard symbol
+ *
+ * test!=INC_CLEAR returns 1 if file can be included again
+ *
+ * NOTE:
+ *
+ * (1) different hard links to the same file are treated as
+ * different files
+ *
+ * (2) symbolic links in combination with .. may cause two
+ * different files to be treated as the same file:
+ *
+ * "../h/<file>" == "/usr/include/sys/../h/<file>" -> "/usr/include/h/<file>"
+ * "h/<file>" -> "/usr/include/h/<file>"
+ */
+
+int
+ppmultiple(register struct ppfile* fp, register struct ppsymbol* test)
+{
+ register struct ppsymbol* status;
+
+ status = fp->guard;
+ message((-3, "search: %s: status=%s%s test=%s", fp->name, status == INC_CLEAR ? "[CLEAR]" : status == INC_TEST ? "[ONCE]" : status == INC_IGNORE ? "[IGNORE]" : status->name, (pp.mode & HOSTED) ? "[HOSTED]" : "", test == INC_CLEAR ? "[CLEAR]" : test == INC_TEST ? "[TEST]" : test->name));
+ if (status == INC_IGNORE)
+ {
+ message((-2, "%s: ignored [%s]", fp->name, pp.ignore));
+ return 0;
+ }
+ if (test == INC_TEST)
+ {
+ if (status != INC_CLEAR)
+ {
+ if (status != INC_TEST && status->macro || !(pp.mode & ALLMULTIPLE) && !(pp.state & STRICT))
+ {
+ if ((pp.mode & (ALLMULTIPLE|LOADING)) == LOADING)
+ fp->guard = INC_IGNORE;
+ if (pp.state & WARN)
+ error(1, "%s: ignored -- already included", fp->name);
+ else
+ message((-3, "%s: ignored -- already included", fp->name));
+ return 0;
+ }
+ return 1;
+ }
+ if ((pp.mode & (ALLMULTIPLE|LOADING)) == LOADING)
+ test = INC_IGNORE;
+ }
+ fp->guard = test;
+ return 1;
+}
+
+/*
+ * search for file using directories in dp
+ */
+
+static int
+search(register struct ppfile* fp, register struct ppdirs* dp, int type, int flags)
+{
+ register char* prefix;
+ register struct ppdirs* up;
+ register struct ppfile* xp;
+ struct ppfile* mp;
+ int fd;
+ int index;
+ int need;
+ int markhosted;
+ char* t;
+
+ if (!(pp.option & PREFIX))
+ prefix = 0;
+ else if ((prefix = strrchr(fp->name, '/')) && prefix > fp->name)
+ {
+ *prefix = 0;
+ t = ppsetfile(fp->name)->name;
+ *prefix = '/';
+ prefix = t;
+ }
+ message((-3, "search: %s %s%s%s%s%s%s type=%s prefix=%s flags=|%s%s%s%s%s%s start=%s=\"%s\" pre=%s lcl=%s vnd=%s std=%s cur=%s",
+ fp->name,
+ (flags & SEARCH_INCLUDE) ? "include" : "exists",
+ (flags & SEARCH_VENDOR) ? " vendor" : "",
+ (flags & SEARCH_HOSTED) ? " hosted" : "",
+ (flags & SEARCH_NEXT) ? " next" : "",
+ (flags & SEARCH_SKIP) ? " skip" : "",
+ (flags & SEARCH_TEST) ? " test" : "",
+ type == T_HEADER ? "<*>" : "\"*\"", prefix,
+ (fp->flags & INC_SELF) ? "SELF|" : "",
+ (fp->flags & INC_EXISTS) ? "EXISTS|" : "",
+ (fp->flags & INC_BOUND(INC_PREFIX)) ? "PREFIX|" : "",
+ (fp->flags & INC_BOUND(INC_LOCAL)) ? "LOCAL|" : "",
+ (fp->flags & INC_BOUND(INC_VENDOR)) ? "VENDOR|" : "",
+ (fp->flags & INC_BOUND(INC_STANDARD)) ? "STANDARD|" : "",
+ dp ? (dp->index == INC_PREFIX ? "pre" : dp->index == INC_LOCAL ? "lcl" : dp->index == INC_VENDOR ? "vnd" : "std") : NiL,
+ dp ? dp->name : NiL,
+ !(fp->flags & INC_MEMBER(INC_PREFIX)) && (xp = fp->bound[INC_PREFIX]) ? xp->name : NiL,
+ !(fp->flags & INC_MEMBER(INC_LOCAL)) && (xp = fp->bound[INC_LOCAL]) ? xp->name : NiL,
+ !(fp->flags & INC_MEMBER(INC_VENDOR)) && (xp = fp->bound[INC_VENDOR]) ? xp->name : NiL,
+ !(fp->flags & INC_MEMBER(INC_STANDARD)) && (xp = fp->bound[INC_STANDARD]) ? xp->name : NiL,
+ error_info.file
+ ));
+ if (flags & SEARCH_HOSTED)
+ need = TYPE_HOSTED;
+ else if (flags & SEARCH_VENDOR)
+ need = TYPE_VENDOR;
+ else
+ need = TYPE_INCLUDE;
+ for (index = -1; dp; dp = dp->next)
+ if (dp->type & need)
+ {
+ message((-3, "search: fp=%s need=%02x index=%d dp=%s type=%02x index=%d", fp->name, need, index, dp->name, dp->type, dp->index));
+#if ARCHIVE
+ if (!(dp->type & (TYPE_ARCHIVE|TYPE_DIRECTORY)))
+ {
+ struct stat st;
+
+ if (stat(dp->name, &st))
+ {
+ message((-3, "search: omit %s", dp->name));
+ dp->type = 0;
+ continue;
+ }
+ if (S_ISREG(st.st_mode))
+ {
+ register char* s;
+ char* e;
+ int delimiter;
+ int variant;
+ unsigned long siz;
+ unsigned long off;
+ struct ppmember* ap;
+ Sfio_t* sp;
+
+ /*
+ * check for vdb header archive
+ */
+
+ if (!(sp = sfopen(NiL, dp->name, "r")))
+ {
+ error(ERROR_SYSTEM|1, "%s: ignored -- cannot open", dp->name);
+ dp->type = 0;
+ continue;
+ }
+ variant = sfsprintf(pp.tmpbuf, MAXTOKEN, "%c%s%c%s:archive", VDB_DELIMITER, VDB_MAGIC, VDB_DELIMITER, pp.pass);
+ if (!(s = sfgetr(sp, '\n', 1)) || !strneq(s, pp.tmpbuf, variant))
+ {
+ sfclose(sp);
+ error(1, "%s: ignored -- not a directory or archive", dp->name);
+ dp->type = 0;
+ continue;
+ }
+
+ /*
+ * parse the options
+ */
+
+ dp->type |= TYPE_ARCHIVE;
+ for (s += variant;;)
+ {
+ while (*s == ' ') s++;
+ e = s;
+ for (t = 0; *s && *s != ' '; s++)
+ if (*s == '=')
+ {
+ *s = 0;
+ t = s + 1;
+ }
+ if (*s)
+ *s++ = 0;
+ if (!*e)
+ break;
+ switch ((int)hashref(pp.strtab, e))
+ {
+ case X_CHECKPOINT:
+#if CHECKPOINT
+ dp->type |= TYPE_CHECKPOINT;
+ break;
+#else
+ error(1, "preprocessor not compiled with checkpoint enabled");
+ goto notvdb;
+#endif
+ case X_HIDE:
+
+ if (t)
+ error(1, "%s: %s: archive option value ignored", e);
+ if (e = strrchr(dp->name, '/'))
+ *e = 0;
+ else
+ dp->name = ".";
+ break;
+ case X_MAP:
+ if (!t)
+ error(1, "%s: archive option value expected", e);
+ else
+ dp->name = strdup(t);
+ break;
+ default:
+ error(1, "%s: unknown archive option", e);
+ break;
+ }
+ }
+ if (sfseek(sp, -(VDB_LENGTH + 1), SEEK_END) <= 0 || !(s = sfgetr(sp, '\n', 1)))
+ {
+ notvdb:
+ sfclose(sp);
+ error(1, "%s: ignored -- cannot load archive", dp->name);
+ dp->type = 0;
+ continue;
+ }
+ if (variant = *s != 0)
+ s++;
+ else if (!(s = sfgetr(sp, '\n', 1)))
+ goto notvdb;
+ if (sfvalue(sp) != (VDB_LENGTH + variant))
+ goto notvdb;
+ if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY) - 1))
+ goto notvdb;
+ delimiter = s[VDB_OFFSET - 1];
+ off = strtol(s + VDB_OFFSET, NiL, 10) - sizeof(VDB_DIRECTORY);
+ siz = strtol(s + VDB_SIZE, NiL, 10);
+ if (sfseek(sp, off, SEEK_SET) != off)
+ goto notvdb;
+ if (!(s = sfreserve(sp, siz + 1, 0)))
+ goto notvdb;
+ s[siz] = 0;
+ if (!strneq(s, VDB_DIRECTORY, sizeof(VDB_DIRECTORY)) - 1)
+ goto notvdb;
+ if (!(s = strchr(s, '\n')))
+ goto notvdb;
+ s++;
+ while (e = strchr(s, '\n'))
+ {
+ delimiter = variant ? *s++ : delimiter;
+ if (!(t = strchr(s, delimiter)))
+ break;
+ *t = 0;
+ if (!streq(s, VDB_DIRECTORY))
+ {
+ pathcanon(s, 0);
+ ap = newof(0, struct ppmember, 1, 0);
+ ap->archive = dp;
+ ap->offset = strtol(t + 1, &t, 10);
+ ap->size = strtol(t + 1, NiL, 10);
+ xp = ppsetfile(s);
+ xp->flags |= INC_MEMBER(dp->index);
+ xp->bound[dp->index] = (struct ppfile*)ap;
+if (pp.test & 0x0020) error(1, "VDB#%d %s %s index=%d data=<%lu,%lu>", __LINE__, dp->name, xp->name, index, ap->offset, ap->size);
+ }
+ s = e + 1;
+ }
+ if (sfseek(sp, 0L, SEEK_SET))
+ goto notvdb;
+ if (!(pp.test & 0x4000) &&
+#if POOL
+ (pp.pool.input || !(dp->type & TYPE_CHECKPOINT))
+#else
+ !(dp->type & TYPE_CHECKPOINT)
+#endif
+ && (dp->info.buffer = sfreserve(sp, off, 0)))
+ dp->type |= TYPE_BUFFER;
+ else
+ {
+ dp->info.sp = sp;
+#if POOL
+ if (pp.pool.input)
+ sfset(sp, SF_SHARE, 1);
+#endif
+ }
+ }
+ else
+ dp->type |= TYPE_DIRECTORY;
+ }
+#endif
+ if (streq(fp->name, "."))
+ continue;
+ if (prefix && *fp->name != '/' && dp->index != INC_PREFIX)
+#if ARCHIVE
+ if (dp->type & TYPE_DIRECTORY)
+#endif
+ {
+ for (up = dp->info.subdir; up; up = up->next)
+ if (up->name == prefix)
+ break;
+ if (!up)
+ {
+ up = newof(0, struct ppdirs, 1, 0);
+ up->name = prefix;
+ up->type = dp->type;
+ up->next = dp->info.subdir;
+ dp->info.subdir = up;
+ if (!*dp->name)
+ t = prefix;
+ else
+ sfsprintf(t = pp.path, PATH_MAX - 1, "%s/%s", dp->name, prefix);
+ if (eaccess(t, X_OK))
+ {
+ message((-3, "search: omit %s", t));
+ continue;
+ }
+ up->type |= TYPE_HOSTED;
+ }
+ else if (!(up->type & TYPE_HOSTED))
+ continue;
+ }
+ mp = xp = 0;
+ if (!(flags & SEARCH_NEXT) && index != dp->index && (!(need & TYPE_HOSTED) || dp->index == INC_STANDARD) && (!(need & TYPE_VENDOR) || dp->index == INC_VENDOR))
+ {
+ if (index >= 0 && !(fp->flags & INC_MEMBER(index)))
+ fp->flags |= INC_BOUND(index);
+ index = dp->index;
+ if (fp->flags & INC_BOUND(index))
+ {
+ xp = fp->bound[index];
+ if (index == INC_PREFIX)
+ {
+ if (*fp->name == '/' || !*dp->name)
+ strcpy(pp.path, fp->name);
+ else
+ sfsprintf(pp.path, PATH_MAX - 1, "%s/%s", dp->name, fp->name);
+ pathcanon(pp.path, 0);
+ if (!xp || !streq(xp->name, pp.path))
+ {
+ fp->bound[index] = xp = ppsetfile(pp.path);
+ if (dp->type & TYPE_HOSTED)
+ xp->flags |= INC_HOSTED;
+ if ((flags & SEARCH_INCLUDE) || (xp->flags & INC_EXISTS))
+ {
+ if (!(flags & SEARCH_INCLUDE))
+ return 0;
+ if (!ppmultiple(xp, INC_TEST))
+ {
+ if (flags & SEARCH_TEST)
+ pp.include = xp->name;
+ return 0;
+ }
+ mp = xp;
+ }
+ }
+ }
+ else if (!xp)
+ {
+ while (dp->next && dp->next->index == index)
+ dp = dp->next;
+ message((-3, "search: omit %s/%s", dp->name, fp->name));
+ continue;
+ }
+ else
+ {
+ strcpy(pp.path, xp->name);
+ if (!(flags & SEARCH_INCLUDE))
+ return 0;
+ if (!ppmultiple(xp, INC_TEST))
+ {
+ if (flags & SEARCH_TEST)
+ pp.include = xp->name;
+ return 0;
+ }
+ mp = xp;
+ }
+ }
+ }
+ if (!(fp->flags & INC_BOUND(index)) || (flags & SEARCH_NEXT))
+ {
+ if (*fp->name == '/' || !*dp->name)
+ strcpy(pp.path, fp->name);
+ else
+ sfsprintf(pp.path, PATH_MAX - 1, "%s/%s", dp->name, fp->name);
+ pathcanon(pp.path, 0);
+ if (!(flags & SEARCH_SKIP))
+ {
+ int found;
+ struct ppinstk* in;
+
+ if (streq(error_info.file, pp.path))
+ found = 1;
+ else
+ {
+ found = 0;
+ for (in = pp.in; in; in = in->prev)
+ if (in->type == IN_FILE && in->file && streq(in->file, pp.path))
+ {
+ found = 1;
+ break;
+ }
+ }
+ if (found)
+ {
+ flags |= SEARCH_FOUND;
+ continue;
+ }
+ if (!(flags & SEARCH_FOUND))
+ continue;
+ }
+ }
+ if ((xp || (xp = ppgetfile(pp.path))) && (xp->flags & INC_SELF))
+ {
+ if (xp->flags & INC_EXISTS)
+ {
+ if (!(flags & SEARCH_INCLUDE))
+ return 0;
+ if (!(flags & SEARCH_NEXT) && mp != xp && (mp = xp) && !ppmultiple(xp, INC_TEST))
+ {
+ if (flags & SEARCH_TEST)
+ pp.include = xp->name;
+ return 0;
+ }
+ }
+ else if (*fp->name == '/')
+ break;
+ else
+ continue;
+ }
+ message((-3, "search: file=%s path=%s", fp->name, pp.path));
+#if ARCHIVE
+if (pp.test & 0x0040) error(1, "SEARCH#%d dir=%s%s%s%s%s file=%s%s path=%s index=%d", __LINE__, dp->name, (dp->type & TYPE_ARCHIVE) ? " ARCHIVE" : "", (dp->type & TYPE_BUFFER) ? " BUFFER" : "", (dp->type & TYPE_CHECKPOINT) ? " CHECKPOINT" : "", (dp->type & TYPE_DIRECTORY) ? " DIRECTORY" : "", fp->name, (fp->flags & INC_MEMBER(index)) ? " MEMBER" : "", pp.path, index);
+ if ((fp->flags & INC_MEMBER(index)) && ((struct ppmember*)fp->bound[index])->archive == dp)
+ {
+ fd = 0;
+ pp.member = (struct ppmember*)fp->bound[index];
+if (pp.test & 0x0010) error(1, "SEARCH#%d file=%s path=%s index=%d data=<%lu,%lu>", __LINE__, fp->name, pp.path, index, pp.member->offset, pp.member->size);
+ }
+ else if (!(dp->type & TYPE_DIRECTORY))
+ continue;
+ else
+#endif
+ {
+ pp.member = 0;
+ fd = (flags & SEARCH_INCLUDE) ? open(pp.path, O_RDONLY) : eaccess(pp.path, R_OK);
+ }
+ if (fd >= 0)
+ {
+ pp.found = dp;
+ if ((pp.option & (PLUSPLUS|NOPROTO)) == PLUSPLUS && !(pp.test & TEST_noproto))
+ {
+ if (dp->c)
+ pp.mode |= MARKC;
+ else
+ pp.mode &= ~MARKC;
+ }
+ if (xp)
+ markhosted = xp->flags & INC_HOSTED;
+ else if (!(markhosted = (dp->type & TYPE_HOSTED)) && dp->index == INC_PREFIX && (pp.mode & (FILEDEPS|HEADERDEPS|INIT)) == FILEDEPS)
+ {
+ up = dp;
+ while ((up = up->next) && !streq(up->name, dp->name));
+ if (up && (up->type & TYPE_HOSTED))
+ markhosted = 1;
+ }
+ if (markhosted)
+ pp.mode |= MARKHOSTED;
+ else
+ pp.mode &= ~MARKHOSTED;
+ xp = ppsetfile(pp.path);
+ if (markhosted)
+ xp->flags |= INC_HOSTED;
+ message((-2, "search: %s -> %s%s%s", fp->name, pp.path, (pp.mode & MARKC) ? " [C]" : "", (pp.mode & MARKHOSTED) ? " [hosted]" : ""));
+#if ARCHIVE
+ if (!pp.member)
+ {
+#endif
+ fp->flags |= INC_BOUND(index);
+ fp->bound[index] = xp;
+ if ((index == INC_STANDARD || index == INC_VENDOR) && type != T_HEADER && !(fp->flags & INC_BOUND(INC_LOCAL)))
+ {
+ fp->flags |= INC_BOUND(INC_LOCAL);
+ fp->bound[INC_LOCAL] = xp;
+ }
+#if ARCHIVE
+ }
+#endif
+ xp->flags |= INC_SELF|INC_EXISTS;
+ if (flags & SEARCH_INCLUDE)
+ {
+ if ((pp.prefix = prefix) || (pp.prefix = pp.in->prefix))
+ message((-2, "search: %s: prefix=%s", xp->name, pp.prefix));
+ if (!(pp.mode & ALLMULTIPLE))
+ {
+ if (xp->guard == INC_CLEAR || xp == mp)
+ xp->guard = INC_TEST;
+ else
+ {
+ if (pp.state & WARN)
+ error(1, "%s: ignored -- already included", xp->name);
+ else
+ message((-3, "%s: ignored -- already included", xp->name));
+ xp->guard = fp->guard = INC_IGNORE;
+#if ARCHIVE
+ if (!pp.member)
+#endif
+ if (fd > 0)
+ close(fd);
+ if (flags & SEARCH_TEST)
+ pp.include = xp->name;
+ return 0;
+ }
+ }
+ pp.include = xp->name;
+ if ((pp.mode & (FILEDEPS|INIT)) == FILEDEPS && ((pp.mode & HEADERDEPS) || !(pp.mode & MARKHOSTED)) && !(xp->flags & INC_LISTED))
+ {
+ xp->flags |= INC_LISTED;
+ if ((pp.column + strlen(xp->name)) >= COLUMN_MAX)
+ {
+ sfprintf(pp.filedeps.sp, " \\\n");
+ pp.column = COLUMN_TAB;
+ index = '\t';
+ }
+ else
+ index = ' ';
+ pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, xp->name);
+ }
+ }
+ return fd;
+ }
+ if (xp)
+ xp->flags |= INC_SELF;
+ if (errno == EMFILE)
+ error(3, "%s: too many open files", fp->name);
+ else if (errno != ENOENT && errno != ENOTDIR)
+ error(ERROR_SYSTEM|1, "%s: cannot open file for reading", pp.path);
+ if (*fp->name == '/')
+ break;
+ }
+ strcpy(pp.path, fp->name);
+ message((-2, "search: %s%s not found", (flags & SEARCH_NEXT) ? "next " : "", fp->name));
+ return -1;
+}
+
+/*
+ * search for an include file
+ * if (flags&SEARCH_INCLUDE) then
+ * if file found then open read file descriptor returned
+ * with pp.path set to the full path and
+ * pp.prefix set to the directory prefix
+ * otherwise 0 returned if file found but ignored
+ * otherwise -1 returned
+ * otherwise
+ * if file found then 0 returned
+ * otherwise -1 returned
+ */
+
+int
+ppsearch(char* file, int type, int flags)
+{
+ register struct ppfile* fp;
+ register char* s;
+ register struct ppdirs* dp;
+ struct oplist* cp;
+ struct ppfile* xp;
+ int dospath;
+ int fd;
+ int index;
+ char name[MAXTOKEN + 1];
+
+ pp.include = 0;
+ fd = -1;
+ dospath = 0;
+ again:
+ pathcanon(file, 0);
+ for (cp = pp.chop; cp; cp = cp->next)
+ if (strneq(file, cp->value, cp->op))
+ {
+ if (cp->value[cp->op + 1])
+ {
+ sfsprintf(name, sizeof(name) - 1, "%s%s", cp->value + cp->op + 1, file + cp->op);
+ message((-3, "chop: %s -> %s", file, name));
+ file = name;
+ }
+ else if (strchr(file + cp->op, '/'))
+ {
+ message((-3, "chop: %s -> %s", file, file + cp->op));
+ file += cp->op;
+ }
+ break;
+ }
+ fp = ppsetfile(file);
+ while ((fp->flags & INC_MAPALL) || (fp->flags & INC_MAPHOSTED) && (pp.mode & HOSTED) || (fp->flags & INC_MAPNOHOSTED) && !(pp.mode & HOSTED))
+ {
+ if (!(xp = fp->bound[type == T_HEADER ? INC_STANDARD : INC_LOCAL]) || xp == fp)
+ break;
+ message((-1, "map: %s -> %s", fp->name, xp->name));
+ fp = xp;
+ }
+ if ((fp->flags & INC_MAPNOLOCAL) && (pp.mode & HOSTED))
+ flags |= SEARCH_HOSTED;
+ else if (pp.vendor)
+ flags |= SEARCH_VENDOR;
+ pp.original = fp;
+ if (type == T_HEADER && strneq(fp->name, "...", 3) && (!fp->name[3] || fp->name[3] == '/'))
+ {
+ if (fp->name[3] == '/')
+ {
+ int n;
+ int m;
+
+ n = strlen(error_info.file);
+ m = strlen(fp->name + 4);
+ if (n < m || !streq(fp->name + 4, error_info.file + n - m))
+ {
+ if ((fd = ppsearch(fp->name + 4, type, flags|SEARCH_TEST)) < 0)
+ return -1;
+ if (fd > 0)
+ close(fd);
+ s = error_info.file;
+ error_info.file = pp.include;
+ fd = ppsearch(fp->name + 4, type, flags|SEARCH_NEXT);
+ error_info.file = s;
+ return fd;
+ }
+ file = error_info.file + n - m;
+ }
+ else if (file = strrchr(error_info.file, '/'))
+ file++;
+ else
+ file = error_info.file;
+ flags |= SEARCH_NEXT;
+#if _HUH_2002_05_28
+ if (pp.in->prefix)
+ {
+ sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, file);
+ fp = ppsetfile(name);
+ if ((fd = ppsearch(fp->name, type, flags)) >= 0)
+ return fd;
+ }
+#endif
+ fp = ppsetfile(file);
+ return ppsearch(fp->name, type, flags);
+ }
+ else if ((flags & SEARCH_INCLUDE) && fp->guard == INC_IGNORE)
+ {
+ strcpy(pp.path, fp->name);
+ message((-2, "%s: ignored", fp->name));
+ return 0;
+ }
+ else if (!(flags & SEARCH_NEXT))
+ flags |= SEARCH_SKIP;
+ pp.prefix = 0;
+ if (type == T_HEADER)
+ dp = pp.stddirs->next;
+ else
+ {
+ dp = pp.lcldirs;
+ if (dp == pp.firstdir)
+ {
+ /*
+ * look in directory of including file first
+ */
+
+ if (error_info.file && (s = strrchr(error_info.file, '/')))
+ {
+ *s = 0;
+ dp->name = ppsetfile(error_info.file)->name;
+ *s = '/';
+ }
+ else
+ dp->name = "";
+ }
+ else if (pp.in->prefix && pp.lcldirs != pp.firstdir)
+ {
+ /*
+ * look in prefix directory of including file first
+ */
+
+ if (*fp->name != '/')
+ {
+ if ((s = strchr(fp->name, '/')) && (fp->name[0]
+!= '.' || fp->name[1] != '.' || fp->name[2] != '/'))
+ {
+ *s = 0;
+ if (!streq(fp->name, pp.in->prefix))
+ fd = 0;
+ *s = '/';
+ }
+ else
+ fd = 0;
+ }
+ if (fd >= 0)
+ {
+ sfsprintf(name, sizeof(name) - 1, "%s/%s", pp.in->prefix, fp->name);
+ pathcanon(name, 0);
+ xp = ppsetfile(name);
+ if ((fd = search(xp, dp, type, flags)) >= 0)
+ return fd;
+ }
+ }
+ }
+ if ((fd = search(fp, dp, type, flags)) < 0)
+ {
+ if ((pp.option & PLUSPLUS) && file != pp.tmpbuf)
+ {
+ s = file + strlen(file);
+ while (s > file && *--s != '/' && *s != '\\' && *s != '.');
+ if (*s != '.')
+ {
+ sfsprintf(pp.tmpbuf, MAXTOKEN, "%s.h", file);
+ file = pp.tmpbuf;
+ goto again;
+ }
+ }
+
+ /*
+ * hackery for msdos files viewed through unix
+ */
+
+ switch (dospath)
+ {
+ case 0:
+ if (s = strchr(file, '\\'))
+ {
+ do *s++ = '/'; while (s = strchr(s, '\\'));
+ pathcanon(file, 0);
+ dospath = 1;
+ goto again;
+ }
+ /*FALLTHROUGH*/
+ case 1:
+ if (ppisid(file[0]) && file[1] == ':' && file[2] == '/')
+ {
+ file[1] = file[0];
+ file[0] = '/';
+ pathcanon(file, 0);
+ dospath = 2;
+ goto again;
+ }
+ break;
+ case 2:
+ file += 2;
+ goto again;
+ }
+ if ((flags & (SEARCH_INCLUDE|SEARCH_NEXT)) == SEARCH_INCLUDE)
+ {
+ if (!(pp.mode & GENDEPS))
+ {
+ if (!(pp.option & ALLPOSSIBLE) || pp.in->prev->prev)
+ error(2, "%s: cannot find include file", file);
+ }
+ else if (!(pp.mode & INIT))
+ {
+ xp = ppsetfile(file);
+ if (!(xp->flags & INC_LISTED))
+ {
+ xp->flags |= INC_LISTED;
+ if ((pp.column + strlen(file)) >= COLUMN_MAX)
+ {
+ sfprintf(pp.filedeps.sp, " \\\n");
+ pp.column = COLUMN_TAB;
+ index = '\t';
+ }
+ else
+ index = ' ';
+ pp.column += sfprintf(pp.filedeps.sp, "%c%s", index, file);
+ }
+ }
+ }
+ }
+ return fd;
+}
diff --git a/usr/src/lib/libpp/common/ppsym.c b/usr/src/lib/libpp/common/ppsym.c
new file mode 100644
index 0000000000..081f1bcd94
--- /dev/null
+++ b/usr/src/lib/libpp/common/ppsym.c
@@ -0,0 +1,94 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * cpp predefined symbol detection support
+ *
+ * with no args stdin is treated as an a.out for
+ * a Reiser derived cpp -- all strings that may
+ * be identifiers are listed on fd 3 (1 if no 3)
+ *
+ * with args the -D argument values are listed on fd 3 (1 if no 3)
+ */
+
+#include <ast.h>
+#include <ctype.h>
+
+int
+main(int argc, char** argv)
+{
+ register int state;
+ register int c;
+ register char* s;
+ Sfio_t* out;
+
+ NoP(argc);
+ if (dup(3) < 0 || !(out = sfnew(NiL, NiL, -1, 3, SF_WRITE)))
+ out = sfstdout;
+ if (*++argv)
+ {
+ while (s = *argv++)
+ if (*s++ == '-' && *s++ == 'D' && isalpha(*s))
+ {
+ while (*s && *s != '=') sfputc(out, *s++);
+ sfputc(out, '\n');
+ }
+ return 0;
+ }
+ state = 0;
+ for (;;)
+ {
+ switch (c = sfgetc(sfstdin))
+ {
+ case EOF:
+ break;
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
+ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
+ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
+ case 's': case 't': case 'u': case 'v': case 'w': case 'x':
+ case 'y': case 'z': case '_':
+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
+ case 'Y': case 'Z':
+ state++;
+ sfputc(out, c);
+ continue;
+ case '0': case '1': case '2': case '3': case '4': case '5':
+ case '6': case '7': case '8': case '9':
+ if (state)
+ {
+ sfputc(out, c);
+ continue;
+ }
+ /*FALLTHROUGH*/
+ default:
+ if (state)
+ {
+ sfputc(out, '\n');
+ state = 0;
+ }
+ continue;
+ }
+ break;
+ }
+ return 0;
+}
diff --git a/usr/src/lib/libpp/common/pptrace.c b/usr/src/lib/libpp/common/pptrace.c
new file mode 100644
index 0000000000..d1b1204817
--- /dev/null
+++ b/usr/src/lib/libpp/common/pptrace.c
@@ -0,0 +1,264 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1986-2007 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+/*
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * preprocessor library trace and debug support
+ */
+
+#include "pplib.h"
+#include "ppfsm.h"
+
+#include <ctype.h>
+
+/*
+ * convert token string to printable form
+ */
+
+char*
+pptokstr(register char* s, register int c)
+{
+ register char* t;
+
+ static char buf[8];
+
+ if (t = s)
+ {
+ while (*t == ' ' || *t == '\t') t++;
+ c = *t ? *t : *s;
+ }
+ switch (c)
+ {
+ case 0:
+ case 0400:
+ return("`EOF'");
+ case ' ':
+ return("`space'");
+ case '\f':
+ return("`formfeed'");
+ case '\n':
+ return("`newline'");
+ case '\t':
+ return("`tab'");
+ case '\v':
+ return("`vertical-tab'");
+ case T_TOKCAT:
+ return("##");
+ default:
+ if (iscntrl(c) || !isprint(c)) sfsprintf(buf, sizeof(buf), "`%03o'", c);
+ else if (s) return(s);
+ else sfsprintf(buf, sizeof(buf), "%c", c);
+ return(buf);
+ }
+}
+
+#if DEBUG & TRACE_debug
+
+#include "ppdebug.h"
+
+/*
+ * return input stream name given index
+ */
+
+char*
+ppinstr(register struct ppinstk* p)
+{
+ register int i;
+
+ static char buf[128];
+
+ for (i = 0; i < elementsof(ppinmap); i++)
+ if (p->type == ppinmap[i].val)
+ {
+ switch (p->type)
+ {
+ case IN_MACRO:
+#if MACDEF
+ case IN_MULTILINE:
+#endif
+ if (p->symbol)
+ {
+ sfsprintf(buf, sizeof(buf), "%s=%s", ppinmap[i].nam, p->symbol->name);
+ return(buf);
+ }
+ break;
+ }
+ return(ppinmap[i].nam);
+ }
+ sfsprintf(buf, sizeof(buf), "UNKNOWN[%d]", p->type);
+ return(buf);
+}
+
+/*
+ * return string given fsm lex state
+ */
+
+char*
+pplexstr(register int lex)
+{
+ register int i;
+ int splice;
+ static char buf[64];
+
+ if (lex < 0) lex &= ~lex;
+ splice = (lex & SPLICE);
+ lex &= 0x7f;
+ for (i = 0; i < (elementsof(pplexmap) - 1) && (lex > pplexmap[i].val || lex == pplexmap[i+1].val); i++);
+ if (lex != pplexmap[i].val)
+ {
+ if (pplexmap[i].val < 0) sfsprintf(buf, sizeof(buf), "%s|0x%04x%s", pplexmap[i].nam, lex, splice ? "|SPLICE" : "");
+ else sfsprintf(buf, sizeof(buf), "%s+%d", pplexmap[i-1].nam, lex - pplexmap[i-1].val, splice ? "|SPLICE" : "");
+ return(buf);
+ }
+ if (splice)
+ {
+ sfsprintf(buf, sizeof(buf), "%s|SPLICE", pplexmap[i].nam);
+ return(buf);
+ }
+ return(pplexmap[i].nam);
+}
+
+/*
+ * return string given map p of size n and flags
+ */
+
+static char*
+ppflagstr(register struct map* p, int n, register long flags)
+{
+ register int i;
+ register int k;
+ register char* s;
+
+ static char buf[128];
+
+ s = buf;
+ for (i = 0; i < n; i++)
+ if (flags & p[i].val)
+ {
+ k = strlen(p[i].nam);
+ if ((elementsof(buf) - 2 - (s - buf)) > k)
+ {
+ if (s > buf) *s++ = '|';
+ strcpy(s, p[i].nam);
+ s += k;
+ }
+ }
+ *s = 0;
+ return(buf);
+}
+
+/*
+ * return string given pp.mode
+ */
+
+char*
+ppmodestr(register long mode)
+{
+ return(ppflagstr(ppmodemap, elementsof(ppmodemap), mode));
+}
+
+/*
+ * return string given pp.option
+ */
+
+char*
+ppoptionstr(register long option)
+{
+ return(ppflagstr(ppoptionmap, elementsof(ppoptionmap), option));
+}
+
+/*
+ * return string given pp.state
+ */
+
+char*
+ppstatestr(register long state)
+{
+ return(ppflagstr(ppstatemap, elementsof(ppstatemap), state));
+}
+
+#include <sig.h>
+
+/*
+ * io stream stack trace
+ * sig==0 registers the handler
+ */
+
+void
+pptrace(int sig)
+{
+ register char* s;
+ register char* x;
+ register struct ppinstk* p;
+ static int handling;
+
+ if (!sig)
+ {
+#ifdef SIGBUS
+ signal(SIGBUS, pptrace);
+#endif
+#ifdef SIGSEGV
+ signal(SIGSEGV, pptrace);
+#endif
+#ifdef SIGILL
+ signal(SIGILL, pptrace);
+#endif
+ signal(SIGQUIT, pptrace);
+ return;
+ }
+ s = fmtsignal(sig);
+ if (handling)
+ {
+ sfprintf(sfstderr, "\n%s during io stack trace\n", s);
+ signal(handling, SIG_DFL);
+ sigunblock(handling);
+ kill(getpid(), handling);
+ pause();
+ error(PANIC, "signal not redelivered");
+ }
+ handling = sig;
+ sfprintf(sfstderr, "\n%s - io stack trace\n", s);
+ for (p = pp.in; p->prev; p = p->prev)
+ {
+ sfprintf(sfstderr, "\n[%s]\n", ppinstr(p));
+ if ((s = pp.in->nextchr) && *s)
+ {
+ if (*s != '\n') sfputc(sfstderr, '\t');
+ x = s + 256;
+ while (*s && s < x)
+ {
+ sfputc(sfstderr, *s);
+ if (*s++ == '\n' && *s && *s != '\n') sfputc(sfstderr, '\t');
+ }
+ if (*s) sfprintf(sfstderr, " ...");
+ }
+ }
+ sfprintf(sfstderr, "\n");
+ handling = 0;
+ signal(sig, SIG_DFL);
+ sigunblock(sig);
+ kill(getpid(), sig);
+ pause();
+ error(PANIC, "signal not redelivered");
+}
+
+#endif
diff --git a/usr/src/lib/libpp/i386/Makefile b/usr/src/lib/libpp/i386/Makefile
new file mode 100644
index 0000000000..f91f0270e9
--- /dev/null
+++ b/usr/src/lib/libpp/i386/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libpp/i386/pp.req b/usr/src/lib/libpp/i386/pp.req
new file mode 100644
index 0000000000..6c6437695b
--- /dev/null
+++ b/usr/src/lib/libpp/i386/pp.req
@@ -0,0 +1,2 @@
+ -lpp
+ -last
diff --git a/usr/src/lib/libpp/i386/pp.yacc b/usr/src/lib/libpp/i386/pp.yacc
new file mode 100644
index 0000000000..1de9080a7a
--- /dev/null
+++ b/usr/src/lib/libpp/i386/pp.yacc
@@ -0,0 +1 @@
+%token /*generated from pp.h*/ T_DOUBLE 292 T_DOUBLE_L 293 T_FLOAT 294 T_DECIMAL 288 T_DECIMAL_L 289 T_DECIMAL_U 290 T_DECIMAL_UL 291 T_OCTAL 296 T_OCTAL_L 297 T_OCTAL_U 298 T_OCTAL_UL 299 T_HEXADECIMAL 304 T_HEXADECIMAL_L 305 T_HEXADECIMAL_U 306 T_HEXADECIMAL_UL 307 T_HEXDOUBLE 308 T_HEXDOUBLE_L 309 T_ID 257 T_INVALID 258 T_CHARCONST 260 T_WCHARCONST 261 T_STRING 262 T_WSTRING 263 T_PTRMEM 264 T_ADDADD 265 T_SUBSUB 266 T_LSHIFT 267 T_RSHIFT 268 T_LE 269 T_GE 270 T_EQ 271 T_NE 272 T_ANDAND 273 T_OROR 274 T_MPYEQ 275 T_DIVEQ 276 T_MODEQ 277 T_ADDEQ 278 T_SUBEQ 279 T_LSHIFTEQ 280 T_RSHIFTEQ 281 T_ANDEQ 282 T_XOREQ 283 T_OREQ 284 T_VARIADIC 286 T_DOTREF 320 T_PTRMEMREF 321 T_SCOPE 322 T_UMINUS 323
diff --git a/usr/src/lib/libpp/i386/ppdebug.h b/usr/src/lib/libpp/i386/ppdebug.h
new file mode 100644
index 0000000000..9c9f29e795
--- /dev/null
+++ b/usr/src/lib/libpp/i386/ppdebug.h
@@ -0,0 +1,211 @@
+/*
+* preprocessor library debug maps
+*/
+struct map
+{
+ char* nam;
+ long val;
+};
+static struct map pplexmap[] =
+{
+ "PROTO", PROTO,
+ "RES1", RES1,
+ "RES1a", RES1a,
+ "RES1e", RES1e,
+ "RES1f", RES1f,
+ "RES1h", RES1h,
+ "RES1l", RES1l,
+ "RES1n", RES1n,
+ "RES1o", RES1o,
+ "RES1t", RES1t,
+ "RES1x", RES1x,
+ "RES1y", RES1y,
+ "COM1", COM1,
+ "COM2", COM2,
+ "COM3", COM3,
+ "COM4", COM4,
+ "COM5", COM5,
+ "COM6", COM6,
+ "COM7", COM7,
+ "NID", NID,
+ "LIT", LIT,
+ "LIT1", LIT1,
+ "LIT2", LIT2,
+ "BAD1", BAD1,
+ "BAD2", BAD2,
+ "DOT", DOT,
+ "DOT2", DOT2,
+ "WS1", WS1,
+ "QUICK", QUICK,
+ "QTOK", QTOK,
+ "QNUM", QNUM,
+ "QEXP", QEXP,
+ "QCOM", QCOM,
+ "QID", QID,
+ "MAC0", MAC0,
+ "MACN", MACN,
+ "HIT0", HIT0,
+ "HITN", HITN,
+ "LIT0", LIT0,
+ "SHARP1", SHARP1,
+ "TOKEN", TOKEN,
+ "OCT1", OCT1,
+ "OCT2", OCT2,
+ "OCT3", OCT3,
+ "NOT1", NOT1,
+ "PCT1", PCT1,
+ "AND1", AND1,
+ "STAR1", STAR1,
+ "PLUS1", PLUS1,
+ "MINUS1", MINUS1,
+ "ARROW1", ARROW1,
+ "COLON1", COLON1,
+ "LT1", LT1,
+ "LSH1", LSH1,
+ "EQ1", EQ1,
+ "RSH1", RSH1,
+ "GT1", GT1,
+ "CIRC1", CIRC1,
+ "OR1", OR1,
+ "DEC1", DEC1,
+ "DEC2", DEC2,
+ "HEX1", HEX1,
+ "HEX2", HEX2,
+ "HEX3", HEX3,
+ "HEX4", HEX4,
+ "HEX5", HEX5,
+ "HEX6", HEX6,
+ "HEX7", HEX7,
+ "HEX8", HEX8,
+ "DBL1", DBL1,
+ "DBL2", DBL2,
+ "DBL3", DBL3,
+ "DBL4", DBL4,
+ "DBL5", DBL5,
+ "DOT1", DOT1,
+ "HDR1", HDR1,
+ "BIN1", BIN1,
+ "TERMINAL", TERMINAL,
+ "S_CHRB", S_CHRB,
+ "S_COMMENT", S_COMMENT,
+ "S_EOB", S_EOB,
+ "S_LITBEG", S_LITBEG,
+ "S_LITEND", S_LITEND,
+ "S_LITESC", S_LITESC,
+ "S_MACRO", S_MACRO,
+ "S_NL", S_NL,
+ "S_QUAL", S_QUAL,
+ "S_SHARP", S_SHARP,
+ "S_VS", S_VS,
+ "S_CHR", S_CHR,
+ "S_HUH", S_HUH,
+ "S_TOK", S_TOK,
+ "S_TOKB", S_TOKB,
+ "S_WS", S_WS,
+ "S_RESERVED", S_RESERVED,
+};
+static struct map ppstatemap[] =
+{
+ "ADD", ADD,
+ "COLLECTING", COLLECTING,
+ "COMPATIBILITY", COMPATIBILITY,
+ "COMPILE", COMPILE,
+ "CONDITIONAL", CONDITIONAL,
+ "DEFINITION", DEFINITION,
+ "DIRECTIVE", DIRECTIVE,
+ "DISABLE", DISABLE,
+ "EOF2NL", EOF2NL,
+ "ESCAPE", ESCAPE,
+ "FILEPOP", FILEPOP,
+ "HEADER", HEADER,
+ "HIDDEN", HIDDEN,
+ "JOINING", JOINING,
+ "NEWLINE", NEWLINE,
+ "NOEXPAND", NOEXPAND,
+ "NOSPACE", NOSPACE,
+ "NOTEXT", NOTEXT,
+ "NOVERTICAL", NOVERTICAL,
+ "PASSEOF", PASSEOF,
+ "PASSTHROUGH", PASSTHROUGH,
+ "QUOTE", QUOTE,
+ "SKIPCONTROL", SKIPCONTROL,
+ "SKIPMACRO", SKIPMACRO,
+ "SPACEOUT", SPACEOUT,
+ "SQUOTE", SQUOTE,
+ "STANDALONE", STANDALONE,
+ "STRICT", STRICT,
+ "STRIP", STRIP,
+ "SYNCLINE", SYNCLINE,
+ "TRANSITION", TRANSITION,
+ "WARN", WARN,
+};
+static struct map ppmodemap[] =
+{
+ "ALLMULTIPLE", ALLMULTIPLE,
+ "BUILTIN", BUILTIN,
+ "CATLITERAL", CATLITERAL,
+ "DUMP", DUMP,
+ "EXPOSE", EXPOSE,
+ "EXTERNALIZE", EXTERNALIZE,
+ "FILEDEPS", FILEDEPS,
+ "GENDEPS", GENDEPS,
+ "HEADERDEPS", HEADERDEPS,
+ "HOSTED", HOSTED,
+ "HOSTEDTRANSITION", HOSTEDTRANSITION,
+ "INACTIVE", INACTIVE,
+ "INIT", INIT,
+ "LOADING", LOADING,
+ "MARKC", MARKC,
+ "MARKHOSTED", MARKHOSTED,
+ "MARKMACRO", MARKMACRO,
+ "PEDANTIC", PEDANTIC,
+ "READONLY", READONLY,
+ "RELAX", RELAX,
+};
+static struct map ppoptionmap[] =
+{
+ "ELSEIF", ELSEIF,
+ "FINAL", FINAL,
+ "HEADEREXPAND", HEADEREXPAND,
+ "HEADEREXPANDALL", HEADEREXPANDALL,
+ "IGNORELINE", IGNORELINE,
+ "INITIAL", INITIAL,
+ "KEEPNOTEXT", KEEPNOTEXT,
+ "KEYARGS", KEYARGS,
+ "MODERN", MODERN,
+ "NATIVE", NATIVE,
+ "NOHASH", NOHASH,
+ "NOISE", NOISE,
+ "NOISEFILTER", NOISEFILTER,
+ "NOPROTO", NOPROTO,
+ "PLUSCOMMENT", PLUSCOMMENT,
+ "PLUSPLUS", PLUSPLUS,
+ "PLUSSPLICE", PLUSSPLICE,
+ "PRAGMAEXPAND", PRAGMAEXPAND,
+ "PREDEFINED", PREDEFINED,
+ "PREDEFINITIONS", PREDEFINITIONS,
+ "PREFIX", PREFIX,
+ "PRESERVE", PRESERVE,
+ "PROTOTYPED", PROTOTYPED,
+ "REGUARD", REGUARD,
+ "SPLICECAT", SPLICECAT,
+ "SPLICESPACE", SPLICESPACE,
+ "STRINGSPAN", STRINGSPAN,
+ "STRINGSPLIT", STRINGSPLIT,
+ "TRUNCATE", TRUNCATE,
+ "ZEOF", ZEOF,
+};
+static struct map ppinmap[] =
+{
+ "BUFFER", IN_BUFFER,
+ "COPY", IN_COPY,
+ "EXPAND", IN_EXPAND,
+ "FILE", IN_FILE,
+ "INIT", IN_INIT,
+ "MACRO", IN_MACRO,
+ "MULTILINE", IN_MULTILINE,
+ "QUOTE", IN_QUOTE,
+ "RESCAN", IN_RESCAN,
+ "SQUOTE", IN_SQUOTE,
+ "STRING", IN_STRING,
+};
diff --git a/usr/src/lib/libpp/i386/ppdef.h b/usr/src/lib/libpp/i386/ppdef.h
new file mode 100644
index 0000000000..6cb3481f8b
--- /dev/null
+++ b/usr/src/lib/libpp/i386/ppdef.h
@@ -0,0 +1,220 @@
+/*
+ *
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * @(#)pp.tab (AT&T Labs Research) 2006-05-09
+ *
+ * C preprocessor tables and states
+ *
+ * + marks extensions to the standard
+ *
+ */
+
+#define DEFINE 1
+#define ELIF 2
+#define ELSE 3
+#define ENDIF 4
+#define ENDMAC 5
+#define ERROR 6
+#define IF 7
+#define IFDEF 8
+#define IFNDEF 9
+#define INCLUDE 10
+#define LET 11
+#define LINE 12
+#define MACDEF 13
+#define PRAGMA 14
+#define RENAME 15
+#define UNDEF 16
+#define WARNING 17
+
+#define X_ALLMULTIPLE 1
+#define X_ALLPOSSIBLE 2
+#define X_BUILTIN 3
+#define X_CATLITERAL 4
+#define X_CDIR 5
+#define X_CHECKPOINT 6
+#define X_CHOP 7
+#define X_COMPATIBILITY 8
+#define X_DEBUG 9
+#define X_ELSEIF 10
+#define X_EXTERNALIZE 11
+#define X_FINAL 12
+#define X_HIDE 13
+#define X_HEADEREXPAND 14
+#define X_HEADEREXPANDALL 15
+#define X_HOSTED 16
+#define X_HOSTEDTRANSITION 17
+#define X_HOSTDIR 18
+#define X_ID 19
+#define X_IGNORE 20
+#define X_INCLUDE 21
+#define X_INITIAL 22
+#define X_KEYARGS 23
+#define X_LINE 24
+#define X_LINEBASE 25
+#define X_LINEFILE 26
+#define X_LINEID 27
+#define X_LINETYPE 28
+#define X_MACREF 29
+#define X_MAP 30
+#define X_MAPINCLUDE 31
+#define X_MODERN 32
+#define X_MULTIPLE 33
+#define X_NATIVE 34
+#define X_NOTE 35
+#define X_OPSPACE 36
+#define X_PASSTHROUGH 37
+#define X_PEDANTIC 38
+#define X_PLUSCOMMENT 39
+#define X_PLUSPLUS 40
+#define X_PLUSSPLICE 41
+#define X_PRAGMAFLAGS 42
+#define X_PRAGMAEXPAND 43
+#define X_PREDEFINED 44
+#define X_PREFIX 45
+#define X_PRESERVE 46
+#define X_PROTO 47
+#define X_PROTOTYPED 48
+#define X_QUOTE 49
+#define X_READONLY 50
+#define X_REGUARD 51
+#define X_RESERVED 52
+#define X_SPACEOUT 53
+#define X_SPLICECAT 54
+#define X_SPLICESPACE 55
+#define X_STANDARD 56
+#define X_STATEMENT 57
+#define X_STRICT 58
+#define X_STRINGSPAN 59
+#define X_STRINGSPLIT 60
+#define X_SYSTEM_HEADER 61
+#define X_TEST 62
+#define X_TEXT 63
+#define X_TRANSITION 64
+#define X_TRUNCATE 65
+#define X_VENDOR 66
+#define X_VERSION 67
+#define X_WARN 68
+#define X_ZEOF 69
+#define X_last_option 69
+
+#define X_DEFINED 70
+#define X_EXISTS 71
+#define X_INCLUDED 72
+#define X_MATCH 73
+#define X_NOTICED 74
+#define X_OPTION 75
+#define X_SIZEOF 76
+#define X_STRCMP 77
+
+#define R_DEFINED 1
+
+#define ADD (1<<0)
+#define COLLECTING (1<<1)
+#define COMPATIBILITY (1<<2)
+#define COMPILE (1<<3)
+#define CONDITIONAL (1<<4)
+#define DEFINITION (1<<5)
+#define DIRECTIVE (1<<6)
+#define DISABLE (1<<7)
+#define EOF2NL (1<<8)
+#define ESCAPE (1<<9)
+#define FILEPOP (1<<10)
+#define HEADER (1<<11)
+#define HIDDEN (1<<12)
+#define JOINING (1<<13)
+#define NEWLINE (1<<14)
+#define NOEXPAND (1L<<15)
+#define NOSPACE (1L<<16)
+#define NOTEXT (1L<<17)
+#define NOVERTICAL (1L<<18)
+#define PASSEOF (1L<<19)
+#define PASSTHROUGH (1L<<20)
+#define QUOTE (1L<<21)
+#define SKIPCONTROL (1L<<22)
+#define SKIPMACRO (1L<<23)
+#define SPACEOUT (1L<<24)
+#define SQUOTE (1L<<25)
+#define STANDALONE (1L<<26)
+#define STRICT (1L<<27)
+#define STRIP (1L<<28)
+#define SYNCLINE (1L<<29)
+#define TRANSITION (1L<<30)
+#define WARN (1L<<31)
+
+#define ALLMULTIPLE (1<<0)
+#define BUILTIN (1<<1)
+#define CATLITERAL (1<<2)
+#define DUMP (1<<3)
+#define EXPOSE (1<<4)
+#define EXTERNALIZE (1<<5)
+#define FILEDEPS (1<<6)
+#define GENDEPS (1<<7)
+#define HEADERDEPS (1<<8)
+#define HOSTED (1<<9)
+#define HOSTEDTRANSITION (1<<10)
+#define INACTIVE (1<<11)
+#define INIT (1<<12)
+#define LOADING (1<<13)
+#define MARKC (1<<14)
+#define MARKHOSTED (1L<<15)
+#define MARKMACRO (1L<<16)
+#define PEDANTIC (1L<<17)
+#define READONLY (1L<<18)
+#define RELAX (1L<<19)
+
+#define ALLPOSSIBLE (1<<0)
+#define DEFINITIONS (1<<1)
+#define ELSEIF (1<<2)
+#define FINAL (1<<3)
+#define HEADEREXPAND (1<<4)
+#define HEADEREXPANDALL (1<<5)
+#define IGNORELINE (1<<6)
+#define INITIAL (1<<7)
+#define KEEPNOTEXT (1<<8)
+#define KEYARGS (1<<9)
+#define MODERN (1<<10)
+#define NATIVE (1<<11)
+#define NOHASH (1<<12)
+#define NOISE (1<<13)
+#define NOISEFILTER (1<<14)
+#define NOPROTO (1L<<15)
+#define PLUSCOMMENT (1L<<16)
+#define PLUSPLUS (1L<<17)
+#define PLUSSPLICE (1L<<18)
+#define PRAGMAEXPAND (1L<<19)
+#define PREDEFINED (1L<<20)
+#define PREDEFINITIONS (1L<<21)
+#define PREFIX (1L<<22)
+#define PRESERVE (1L<<23)
+#define PROTOTYPED (1L<<24)
+#define REGUARD (1L<<25)
+#define SPLICECAT (1L<<26)
+#define SPLICESPACE (1L<<27)
+#define STRINGSPAN (1L<<28)
+#define STRINGSPLIT (1L<<29)
+#define TRUNCATE (1L<<30)
+#define ZEOF (1L<<31)
+
+#define V__PRAGMA 78
+#define V_ARGC 79
+#define V_BASE 80
+#define V_DATE 81
+#define V_FILE 82
+#define V_FUNCTION 83
+#define V_LINE 84
+#define V_PATH 85
+#define V_SOURCE 86
+#define V_STDC 87
+#define V_TIME 88
+#define V_VERSION 89
+#define V_DEFAULT 90
+#define V_DIRECTIVE 91
+#define V_EMPTY 92
+#define V_GETENV 93
+#define V_GETMAC 94
+#define V_GETOPT 95
+#define V_GETPRD 96
+#define V_ITERATE 97
diff --git a/usr/src/lib/libpp/i386/pptab.h b/usr/src/lib/libpp/i386/pptab.h
new file mode 100644
index 0000000000..d153e8e65c
--- /dev/null
+++ b/usr/src/lib/libpp/i386/pptab.h
@@ -0,0 +1,152 @@
+/*
+ *
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * @(#)pp.tab (AT&T Labs Research) 2006-05-09
+ *
+ * C preprocessor tables and states
+ *
+ * + marks extensions to the standard
+ *
+ */
+
+static struct ppkeyword directives[] =
+{
+ "define", DEFINE,
+ "elif", ELIF,
+ "else", ELSE,
+ "endif", ENDIF,
+ "+endmac", ENDMAC,
+ "error", ERROR,
+ "if", IF,
+ "ifdef", IFDEF,
+ "ifndef", IFNDEF,
+ "include", INCLUDE,
+ "+let", LET,
+ "line", LINE,
+ "+macdef", MACDEF,
+ "pragma", PRAGMA,
+ "+rename", RENAME,
+ "undef", UNDEF,
+ "+warning", WARNING,
+ 0, 0
+};
+
+static struct ppkeyword options[] =
+{
+ "allmultiple", X_ALLMULTIPLE,
+ "allpossible", X_ALLPOSSIBLE,
+ "builtin", X_BUILTIN,
+ "catliteral", X_CATLITERAL,
+ "cdir", X_CDIR,
+ "checkpoint", X_CHECKPOINT,
+ "chop", X_CHOP,
+ "compatibility", X_COMPATIBILITY,
+ "debug", X_DEBUG,
+ "elseif", X_ELSEIF,
+ "externalize", X_EXTERNALIZE,
+ "final", X_FINAL,
+ "hide", X_HIDE,
+ "headerexpand", X_HEADEREXPAND,
+ "headerexpandall", X_HEADEREXPANDALL,
+ "hosted", X_HOSTED,
+ "hostedtransition", X_HOSTEDTRANSITION,
+ "hostdir", X_HOSTDIR,
+ "id", X_ID,
+ "ignore", X_IGNORE,
+ "include", X_INCLUDE,
+ "initial", X_INITIAL,
+ "keyargs", X_KEYARGS,
+ "line", X_LINE,
+ "linebase", X_LINEBASE,
+ "linefile", X_LINEFILE,
+ "lineid", X_LINEID,
+ "linetype", X_LINETYPE,
+ "macref", X_MACREF,
+ "map", X_MAP,
+ "mapinclude", X_MAPINCLUDE,
+ "modern", X_MODERN,
+ "multiple", X_MULTIPLE,
+ "native", X_NATIVE,
+ "note", X_NOTE,
+ "opspace", X_OPSPACE,
+ "passthrough", X_PASSTHROUGH,
+ "pedantic", X_PEDANTIC,
+ "pluscomment", X_PLUSCOMMENT,
+ "plusplus", X_PLUSPLUS,
+ "plussplice", X_PLUSSPLICE,
+ "pragmaflags", X_PRAGMAFLAGS,
+ "pragmaexpand", X_PRAGMAEXPAND,
+ "predefined", X_PREDEFINED,
+ "prefix", X_PREFIX,
+ "preserve", X_PRESERVE,
+ "proto", X_PROTO,
+ "prototyped", X_PROTOTYPED,
+ "quote", X_QUOTE,
+ "readonly", X_READONLY,
+ "reguard", X_REGUARD,
+ "reserved", X_RESERVED,
+ "spaceout", X_SPACEOUT,
+ "splicecat", X_SPLICECAT,
+ "splicespace", X_SPLICESPACE,
+ "standard", X_STANDARD,
+ "statement", X_STATEMENT,
+ "strict", X_STRICT,
+ "stringspan", X_STRINGSPAN,
+ "stringsplit", X_STRINGSPLIT,
+ "system_header", X_SYSTEM_HEADER,
+ "test", X_TEST,
+ "text", X_TEXT,
+ "transition", X_TRANSITION,
+ "truncate", X_TRUNCATE,
+ "vendor", X_VENDOR,
+ "version", X_VERSION,
+ "warn", X_WARN,
+ "zeof", X_ZEOF,
+ 0, 0
+};
+
+static struct ppkeyword predicates[] =
+{
+ "defined", X_DEFINED,
+ "+exists", X_EXISTS,
+ "+included", X_INCLUDED,
+ "+match", X_MATCH,
+ "+noticed", X_NOTICED,
+ "+option", X_OPTION,
+ "sizeof", X_SIZEOF,
+ "+strcmp", X_STRCMP,
+ 0, 0
+};
+
+static struct ppkeyword readonlys[] =
+{
+ "defined", R_DEFINED,
+ 0, 0
+};
+
+static struct ppkeyword variables[] =
+{
+ "_Pragma", V__PRAGMA,
+ "+ARGC", V_ARGC,
+ "+BASE", V_BASE,
+ "DATE", V_DATE,
+ "FILE", V_FILE,
+ "+FUNCTION", V_FUNCTION,
+ "LINE", V_LINE,
+ "+PATH", V_PATH,
+ "+SOURCE", V_SOURCE,
+ "-STDC", V_STDC,
+ "TIME", V_TIME,
+ "+VERSION", V_VERSION,
+ "-default", V_DEFAULT,
+ "-directive", V_DIRECTIVE,
+ "-empty", V_EMPTY,
+ "-getenv", V_GETENV,
+ "-getmac", V_GETMAC,
+ "-getopt", V_GETOPT,
+ "-getprd", V_GETPRD,
+ "-iterate", V_ITERATE,
+ 0, 0
+};
diff --git a/usr/src/lib/libpp/mapfile-vers b/usr/src/lib/libpp/mapfile-vers
new file mode 100644
index 0000000000..43e4584b85
--- /dev/null
+++ b/usr/src/lib/libpp/mapfile-vers
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+SUNWprivate_1.1 {
+ global:
+ pp;
+ ppop;
+ pplex;
+ ppinput;
+ ppargs;
+
+ local:
+ *;
+};
diff --git a/usr/src/lib/libpp/sparc/Makefile b/usr/src/lib/libpp/sparc/Makefile
new file mode 100644
index 0000000000..f91f0270e9
--- /dev/null
+++ b/usr/src/lib/libpp/sparc/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# ident "%Z%%M% %I% %E% SMI"
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libpp/sparc/pp.req b/usr/src/lib/libpp/sparc/pp.req
new file mode 100644
index 0000000000..6c6437695b
--- /dev/null
+++ b/usr/src/lib/libpp/sparc/pp.req
@@ -0,0 +1,2 @@
+ -lpp
+ -last
diff --git a/usr/src/lib/libpp/sparc/pp.yacc b/usr/src/lib/libpp/sparc/pp.yacc
new file mode 100644
index 0000000000..1de9080a7a
--- /dev/null
+++ b/usr/src/lib/libpp/sparc/pp.yacc
@@ -0,0 +1 @@
+%token /*generated from pp.h*/ T_DOUBLE 292 T_DOUBLE_L 293 T_FLOAT 294 T_DECIMAL 288 T_DECIMAL_L 289 T_DECIMAL_U 290 T_DECIMAL_UL 291 T_OCTAL 296 T_OCTAL_L 297 T_OCTAL_U 298 T_OCTAL_UL 299 T_HEXADECIMAL 304 T_HEXADECIMAL_L 305 T_HEXADECIMAL_U 306 T_HEXADECIMAL_UL 307 T_HEXDOUBLE 308 T_HEXDOUBLE_L 309 T_ID 257 T_INVALID 258 T_CHARCONST 260 T_WCHARCONST 261 T_STRING 262 T_WSTRING 263 T_PTRMEM 264 T_ADDADD 265 T_SUBSUB 266 T_LSHIFT 267 T_RSHIFT 268 T_LE 269 T_GE 270 T_EQ 271 T_NE 272 T_ANDAND 273 T_OROR 274 T_MPYEQ 275 T_DIVEQ 276 T_MODEQ 277 T_ADDEQ 278 T_SUBEQ 279 T_LSHIFTEQ 280 T_RSHIFTEQ 281 T_ANDEQ 282 T_XOREQ 283 T_OREQ 284 T_VARIADIC 286 T_DOTREF 320 T_PTRMEMREF 321 T_SCOPE 322 T_UMINUS 323
diff --git a/usr/src/lib/libpp/sparc/ppdebug.h b/usr/src/lib/libpp/sparc/ppdebug.h
new file mode 100644
index 0000000000..9c9f29e795
--- /dev/null
+++ b/usr/src/lib/libpp/sparc/ppdebug.h
@@ -0,0 +1,211 @@
+/*
+* preprocessor library debug maps
+*/
+struct map
+{
+ char* nam;
+ long val;
+};
+static struct map pplexmap[] =
+{
+ "PROTO", PROTO,
+ "RES1", RES1,
+ "RES1a", RES1a,
+ "RES1e", RES1e,
+ "RES1f", RES1f,
+ "RES1h", RES1h,
+ "RES1l", RES1l,
+ "RES1n", RES1n,
+ "RES1o", RES1o,
+ "RES1t", RES1t,
+ "RES1x", RES1x,
+ "RES1y", RES1y,
+ "COM1", COM1,
+ "COM2", COM2,
+ "COM3", COM3,
+ "COM4", COM4,
+ "COM5", COM5,
+ "COM6", COM6,
+ "COM7", COM7,
+ "NID", NID,
+ "LIT", LIT,
+ "LIT1", LIT1,
+ "LIT2", LIT2,
+ "BAD1", BAD1,
+ "BAD2", BAD2,
+ "DOT", DOT,
+ "DOT2", DOT2,
+ "WS1", WS1,
+ "QUICK", QUICK,
+ "QTOK", QTOK,
+ "QNUM", QNUM,
+ "QEXP", QEXP,
+ "QCOM", QCOM,
+ "QID", QID,
+ "MAC0", MAC0,
+ "MACN", MACN,
+ "HIT0", HIT0,
+ "HITN", HITN,
+ "LIT0", LIT0,
+ "SHARP1", SHARP1,
+ "TOKEN", TOKEN,
+ "OCT1", OCT1,
+ "OCT2", OCT2,
+ "OCT3", OCT3,
+ "NOT1", NOT1,
+ "PCT1", PCT1,
+ "AND1", AND1,
+ "STAR1", STAR1,
+ "PLUS1", PLUS1,
+ "MINUS1", MINUS1,
+ "ARROW1", ARROW1,
+ "COLON1", COLON1,
+ "LT1", LT1,
+ "LSH1", LSH1,
+ "EQ1", EQ1,
+ "RSH1", RSH1,
+ "GT1", GT1,
+ "CIRC1", CIRC1,
+ "OR1", OR1,
+ "DEC1", DEC1,
+ "DEC2", DEC2,
+ "HEX1", HEX1,
+ "HEX2", HEX2,
+ "HEX3", HEX3,
+ "HEX4", HEX4,
+ "HEX5", HEX5,
+ "HEX6", HEX6,
+ "HEX7", HEX7,
+ "HEX8", HEX8,
+ "DBL1", DBL1,
+ "DBL2", DBL2,
+ "DBL3", DBL3,
+ "DBL4", DBL4,
+ "DBL5", DBL5,
+ "DOT1", DOT1,
+ "HDR1", HDR1,
+ "BIN1", BIN1,
+ "TERMINAL", TERMINAL,
+ "S_CHRB", S_CHRB,
+ "S_COMMENT", S_COMMENT,
+ "S_EOB", S_EOB,
+ "S_LITBEG", S_LITBEG,
+ "S_LITEND", S_LITEND,
+ "S_LITESC", S_LITESC,
+ "S_MACRO", S_MACRO,
+ "S_NL", S_NL,
+ "S_QUAL", S_QUAL,
+ "S_SHARP", S_SHARP,
+ "S_VS", S_VS,
+ "S_CHR", S_CHR,
+ "S_HUH", S_HUH,
+ "S_TOK", S_TOK,
+ "S_TOKB", S_TOKB,
+ "S_WS", S_WS,
+ "S_RESERVED", S_RESERVED,
+};
+static struct map ppstatemap[] =
+{
+ "ADD", ADD,
+ "COLLECTING", COLLECTING,
+ "COMPATIBILITY", COMPATIBILITY,
+ "COMPILE", COMPILE,
+ "CONDITIONAL", CONDITIONAL,
+ "DEFINITION", DEFINITION,
+ "DIRECTIVE", DIRECTIVE,
+ "DISABLE", DISABLE,
+ "EOF2NL", EOF2NL,
+ "ESCAPE", ESCAPE,
+ "FILEPOP", FILEPOP,
+ "HEADER", HEADER,
+ "HIDDEN", HIDDEN,
+ "JOINING", JOINING,
+ "NEWLINE", NEWLINE,
+ "NOEXPAND", NOEXPAND,
+ "NOSPACE", NOSPACE,
+ "NOTEXT", NOTEXT,
+ "NOVERTICAL", NOVERTICAL,
+ "PASSEOF", PASSEOF,
+ "PASSTHROUGH", PASSTHROUGH,
+ "QUOTE", QUOTE,
+ "SKIPCONTROL", SKIPCONTROL,
+ "SKIPMACRO", SKIPMACRO,
+ "SPACEOUT", SPACEOUT,
+ "SQUOTE", SQUOTE,
+ "STANDALONE", STANDALONE,
+ "STRICT", STRICT,
+ "STRIP", STRIP,
+ "SYNCLINE", SYNCLINE,
+ "TRANSITION", TRANSITION,
+ "WARN", WARN,
+};
+static struct map ppmodemap[] =
+{
+ "ALLMULTIPLE", ALLMULTIPLE,
+ "BUILTIN", BUILTIN,
+ "CATLITERAL", CATLITERAL,
+ "DUMP", DUMP,
+ "EXPOSE", EXPOSE,
+ "EXTERNALIZE", EXTERNALIZE,
+ "FILEDEPS", FILEDEPS,
+ "GENDEPS", GENDEPS,
+ "HEADERDEPS", HEADERDEPS,
+ "HOSTED", HOSTED,
+ "HOSTEDTRANSITION", HOSTEDTRANSITION,
+ "INACTIVE", INACTIVE,
+ "INIT", INIT,
+ "LOADING", LOADING,
+ "MARKC", MARKC,
+ "MARKHOSTED", MARKHOSTED,
+ "MARKMACRO", MARKMACRO,
+ "PEDANTIC", PEDANTIC,
+ "READONLY", READONLY,
+ "RELAX", RELAX,
+};
+static struct map ppoptionmap[] =
+{
+ "ELSEIF", ELSEIF,
+ "FINAL", FINAL,
+ "HEADEREXPAND", HEADEREXPAND,
+ "HEADEREXPANDALL", HEADEREXPANDALL,
+ "IGNORELINE", IGNORELINE,
+ "INITIAL", INITIAL,
+ "KEEPNOTEXT", KEEPNOTEXT,
+ "KEYARGS", KEYARGS,
+ "MODERN", MODERN,
+ "NATIVE", NATIVE,
+ "NOHASH", NOHASH,
+ "NOISE", NOISE,
+ "NOISEFILTER", NOISEFILTER,
+ "NOPROTO", NOPROTO,
+ "PLUSCOMMENT", PLUSCOMMENT,
+ "PLUSPLUS", PLUSPLUS,
+ "PLUSSPLICE", PLUSSPLICE,
+ "PRAGMAEXPAND", PRAGMAEXPAND,
+ "PREDEFINED", PREDEFINED,
+ "PREDEFINITIONS", PREDEFINITIONS,
+ "PREFIX", PREFIX,
+ "PRESERVE", PRESERVE,
+ "PROTOTYPED", PROTOTYPED,
+ "REGUARD", REGUARD,
+ "SPLICECAT", SPLICECAT,
+ "SPLICESPACE", SPLICESPACE,
+ "STRINGSPAN", STRINGSPAN,
+ "STRINGSPLIT", STRINGSPLIT,
+ "TRUNCATE", TRUNCATE,
+ "ZEOF", ZEOF,
+};
+static struct map ppinmap[] =
+{
+ "BUFFER", IN_BUFFER,
+ "COPY", IN_COPY,
+ "EXPAND", IN_EXPAND,
+ "FILE", IN_FILE,
+ "INIT", IN_INIT,
+ "MACRO", IN_MACRO,
+ "MULTILINE", IN_MULTILINE,
+ "QUOTE", IN_QUOTE,
+ "RESCAN", IN_RESCAN,
+ "SQUOTE", IN_SQUOTE,
+ "STRING", IN_STRING,
+};
diff --git a/usr/src/lib/libpp/sparc/ppdef.h b/usr/src/lib/libpp/sparc/ppdef.h
new file mode 100644
index 0000000000..6cb3481f8b
--- /dev/null
+++ b/usr/src/lib/libpp/sparc/ppdef.h
@@ -0,0 +1,220 @@
+/*
+ *
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * @(#)pp.tab (AT&T Labs Research) 2006-05-09
+ *
+ * C preprocessor tables and states
+ *
+ * + marks extensions to the standard
+ *
+ */
+
+#define DEFINE 1
+#define ELIF 2
+#define ELSE 3
+#define ENDIF 4
+#define ENDMAC 5
+#define ERROR 6
+#define IF 7
+#define IFDEF 8
+#define IFNDEF 9
+#define INCLUDE 10
+#define LET 11
+#define LINE 12
+#define MACDEF 13
+#define PRAGMA 14
+#define RENAME 15
+#define UNDEF 16
+#define WARNING 17
+
+#define X_ALLMULTIPLE 1
+#define X_ALLPOSSIBLE 2
+#define X_BUILTIN 3
+#define X_CATLITERAL 4
+#define X_CDIR 5
+#define X_CHECKPOINT 6
+#define X_CHOP 7
+#define X_COMPATIBILITY 8
+#define X_DEBUG 9
+#define X_ELSEIF 10
+#define X_EXTERNALIZE 11
+#define X_FINAL 12
+#define X_HIDE 13
+#define X_HEADEREXPAND 14
+#define X_HEADEREXPANDALL 15
+#define X_HOSTED 16
+#define X_HOSTEDTRANSITION 17
+#define X_HOSTDIR 18
+#define X_ID 19
+#define X_IGNORE 20
+#define X_INCLUDE 21
+#define X_INITIAL 22
+#define X_KEYARGS 23
+#define X_LINE 24
+#define X_LINEBASE 25
+#define X_LINEFILE 26
+#define X_LINEID 27
+#define X_LINETYPE 28
+#define X_MACREF 29
+#define X_MAP 30
+#define X_MAPINCLUDE 31
+#define X_MODERN 32
+#define X_MULTIPLE 33
+#define X_NATIVE 34
+#define X_NOTE 35
+#define X_OPSPACE 36
+#define X_PASSTHROUGH 37
+#define X_PEDANTIC 38
+#define X_PLUSCOMMENT 39
+#define X_PLUSPLUS 40
+#define X_PLUSSPLICE 41
+#define X_PRAGMAFLAGS 42
+#define X_PRAGMAEXPAND 43
+#define X_PREDEFINED 44
+#define X_PREFIX 45
+#define X_PRESERVE 46
+#define X_PROTO 47
+#define X_PROTOTYPED 48
+#define X_QUOTE 49
+#define X_READONLY 50
+#define X_REGUARD 51
+#define X_RESERVED 52
+#define X_SPACEOUT 53
+#define X_SPLICECAT 54
+#define X_SPLICESPACE 55
+#define X_STANDARD 56
+#define X_STATEMENT 57
+#define X_STRICT 58
+#define X_STRINGSPAN 59
+#define X_STRINGSPLIT 60
+#define X_SYSTEM_HEADER 61
+#define X_TEST 62
+#define X_TEXT 63
+#define X_TRANSITION 64
+#define X_TRUNCATE 65
+#define X_VENDOR 66
+#define X_VERSION 67
+#define X_WARN 68
+#define X_ZEOF 69
+#define X_last_option 69
+
+#define X_DEFINED 70
+#define X_EXISTS 71
+#define X_INCLUDED 72
+#define X_MATCH 73
+#define X_NOTICED 74
+#define X_OPTION 75
+#define X_SIZEOF 76
+#define X_STRCMP 77
+
+#define R_DEFINED 1
+
+#define ADD (1<<0)
+#define COLLECTING (1<<1)
+#define COMPATIBILITY (1<<2)
+#define COMPILE (1<<3)
+#define CONDITIONAL (1<<4)
+#define DEFINITION (1<<5)
+#define DIRECTIVE (1<<6)
+#define DISABLE (1<<7)
+#define EOF2NL (1<<8)
+#define ESCAPE (1<<9)
+#define FILEPOP (1<<10)
+#define HEADER (1<<11)
+#define HIDDEN (1<<12)
+#define JOINING (1<<13)
+#define NEWLINE (1<<14)
+#define NOEXPAND (1L<<15)
+#define NOSPACE (1L<<16)
+#define NOTEXT (1L<<17)
+#define NOVERTICAL (1L<<18)
+#define PASSEOF (1L<<19)
+#define PASSTHROUGH (1L<<20)
+#define QUOTE (1L<<21)
+#define SKIPCONTROL (1L<<22)
+#define SKIPMACRO (1L<<23)
+#define SPACEOUT (1L<<24)
+#define SQUOTE (1L<<25)
+#define STANDALONE (1L<<26)
+#define STRICT (1L<<27)
+#define STRIP (1L<<28)
+#define SYNCLINE (1L<<29)
+#define TRANSITION (1L<<30)
+#define WARN (1L<<31)
+
+#define ALLMULTIPLE (1<<0)
+#define BUILTIN (1<<1)
+#define CATLITERAL (1<<2)
+#define DUMP (1<<3)
+#define EXPOSE (1<<4)
+#define EXTERNALIZE (1<<5)
+#define FILEDEPS (1<<6)
+#define GENDEPS (1<<7)
+#define HEADERDEPS (1<<8)
+#define HOSTED (1<<9)
+#define HOSTEDTRANSITION (1<<10)
+#define INACTIVE (1<<11)
+#define INIT (1<<12)
+#define LOADING (1<<13)
+#define MARKC (1<<14)
+#define MARKHOSTED (1L<<15)
+#define MARKMACRO (1L<<16)
+#define PEDANTIC (1L<<17)
+#define READONLY (1L<<18)
+#define RELAX (1L<<19)
+
+#define ALLPOSSIBLE (1<<0)
+#define DEFINITIONS (1<<1)
+#define ELSEIF (1<<2)
+#define FINAL (1<<3)
+#define HEADEREXPAND (1<<4)
+#define HEADEREXPANDALL (1<<5)
+#define IGNORELINE (1<<6)
+#define INITIAL (1<<7)
+#define KEEPNOTEXT (1<<8)
+#define KEYARGS (1<<9)
+#define MODERN (1<<10)
+#define NATIVE (1<<11)
+#define NOHASH (1<<12)
+#define NOISE (1<<13)
+#define NOISEFILTER (1<<14)
+#define NOPROTO (1L<<15)
+#define PLUSCOMMENT (1L<<16)
+#define PLUSPLUS (1L<<17)
+#define PLUSSPLICE (1L<<18)
+#define PRAGMAEXPAND (1L<<19)
+#define PREDEFINED (1L<<20)
+#define PREDEFINITIONS (1L<<21)
+#define PREFIX (1L<<22)
+#define PRESERVE (1L<<23)
+#define PROTOTYPED (1L<<24)
+#define REGUARD (1L<<25)
+#define SPLICECAT (1L<<26)
+#define SPLICESPACE (1L<<27)
+#define STRINGSPAN (1L<<28)
+#define STRINGSPLIT (1L<<29)
+#define TRUNCATE (1L<<30)
+#define ZEOF (1L<<31)
+
+#define V__PRAGMA 78
+#define V_ARGC 79
+#define V_BASE 80
+#define V_DATE 81
+#define V_FILE 82
+#define V_FUNCTION 83
+#define V_LINE 84
+#define V_PATH 85
+#define V_SOURCE 86
+#define V_STDC 87
+#define V_TIME 88
+#define V_VERSION 89
+#define V_DEFAULT 90
+#define V_DIRECTIVE 91
+#define V_EMPTY 92
+#define V_GETENV 93
+#define V_GETMAC 94
+#define V_GETOPT 95
+#define V_GETPRD 96
+#define V_ITERATE 97
diff --git a/usr/src/lib/libpp/sparc/pptab.h b/usr/src/lib/libpp/sparc/pptab.h
new file mode 100644
index 0000000000..d153e8e65c
--- /dev/null
+++ b/usr/src/lib/libpp/sparc/pptab.h
@@ -0,0 +1,152 @@
+/*
+ *
+ * Glenn Fowler
+ * AT&T Research
+ *
+ * @(#)pp.tab (AT&T Labs Research) 2006-05-09
+ *
+ * C preprocessor tables and states
+ *
+ * + marks extensions to the standard
+ *
+ */
+
+static struct ppkeyword directives[] =
+{
+ "define", DEFINE,
+ "elif", ELIF,
+ "else", ELSE,
+ "endif", ENDIF,
+ "+endmac", ENDMAC,
+ "error", ERROR,
+ "if", IF,
+ "ifdef", IFDEF,
+ "ifndef", IFNDEF,
+ "include", INCLUDE,
+ "+let", LET,
+ "line", LINE,
+ "+macdef", MACDEF,
+ "pragma", PRAGMA,
+ "+rename", RENAME,
+ "undef", UNDEF,
+ "+warning", WARNING,
+ 0, 0
+};
+
+static struct ppkeyword options[] =
+{
+ "allmultiple", X_ALLMULTIPLE,
+ "allpossible", X_ALLPOSSIBLE,
+ "builtin", X_BUILTIN,
+ "catliteral", X_CATLITERAL,
+ "cdir", X_CDIR,
+ "checkpoint", X_CHECKPOINT,
+ "chop", X_CHOP,
+ "compatibility", X_COMPATIBILITY,
+ "debug", X_DEBUG,
+ "elseif", X_ELSEIF,
+ "externalize", X_EXTERNALIZE,
+ "final", X_FINAL,
+ "hide", X_HIDE,
+ "headerexpand", X_HEADEREXPAND,
+ "headerexpandall", X_HEADEREXPANDALL,
+ "hosted", X_HOSTED,
+ "hostedtransition", X_HOSTEDTRANSITION,
+ "hostdir", X_HOSTDIR,
+ "id", X_ID,
+ "ignore", X_IGNORE,
+ "include", X_INCLUDE,
+ "initial", X_INITIAL,
+ "keyargs", X_KEYARGS,
+ "line", X_LINE,
+ "linebase", X_LINEBASE,
+ "linefile", X_LINEFILE,
+ "lineid", X_LINEID,
+ "linetype", X_LINETYPE,
+ "macref", X_MACREF,
+ "map", X_MAP,
+ "mapinclude", X_MAPINCLUDE,
+ "modern", X_MODERN,
+ "multiple", X_MULTIPLE,
+ "native", X_NATIVE,
+ "note", X_NOTE,
+ "opspace", X_OPSPACE,
+ "passthrough", X_PASSTHROUGH,
+ "pedantic", X_PEDANTIC,
+ "pluscomment", X_PLUSCOMMENT,
+ "plusplus", X_PLUSPLUS,
+ "plussplice", X_PLUSSPLICE,
+ "pragmaflags", X_PRAGMAFLAGS,
+ "pragmaexpand", X_PRAGMAEXPAND,
+ "predefined", X_PREDEFINED,
+ "prefix", X_PREFIX,
+ "preserve", X_PRESERVE,
+ "proto", X_PROTO,
+ "prototyped", X_PROTOTYPED,
+ "quote", X_QUOTE,
+ "readonly", X_READONLY,
+ "reguard", X_REGUARD,
+ "reserved", X_RESERVED,
+ "spaceout", X_SPACEOUT,
+ "splicecat", X_SPLICECAT,
+ "splicespace", X_SPLICESPACE,
+ "standard", X_STANDARD,
+ "statement", X_STATEMENT,
+ "strict", X_STRICT,
+ "stringspan", X_STRINGSPAN,
+ "stringsplit", X_STRINGSPLIT,
+ "system_header", X_SYSTEM_HEADER,
+ "test", X_TEST,
+ "text", X_TEXT,
+ "transition", X_TRANSITION,
+ "truncate", X_TRUNCATE,
+ "vendor", X_VENDOR,
+ "version", X_VERSION,
+ "warn", X_WARN,
+ "zeof", X_ZEOF,
+ 0, 0
+};
+
+static struct ppkeyword predicates[] =
+{
+ "defined", X_DEFINED,
+ "+exists", X_EXISTS,
+ "+included", X_INCLUDED,
+ "+match", X_MATCH,
+ "+noticed", X_NOTICED,
+ "+option", X_OPTION,
+ "sizeof", X_SIZEOF,
+ "+strcmp", X_STRCMP,
+ 0, 0
+};
+
+static struct ppkeyword readonlys[] =
+{
+ "defined", R_DEFINED,
+ 0, 0
+};
+
+static struct ppkeyword variables[] =
+{
+ "_Pragma", V__PRAGMA,
+ "+ARGC", V_ARGC,
+ "+BASE", V_BASE,
+ "DATE", V_DATE,
+ "FILE", V_FILE,
+ "+FUNCTION", V_FUNCTION,
+ "LINE", V_LINE,
+ "+PATH", V_PATH,
+ "+SOURCE", V_SOURCE,
+ "-STDC", V_STDC,
+ "TIME", V_TIME,
+ "+VERSION", V_VERSION,
+ "-default", V_DEFAULT,
+ "-directive", V_DIRECTIVE,
+ "-empty", V_EMPTY,
+ "-getenv", V_GETENV,
+ "-getmac", V_GETMAC,
+ "-getopt", V_GETOPT,
+ "-getprd", V_GETPRD,
+ "-iterate", V_ITERATE,
+ 0, 0
+};