169112eddSAli Bahrami /*
269112eddSAli Bahrami  * CDDL HEADER START
369112eddSAli Bahrami  *
469112eddSAli Bahrami  * The contents of this file are subject to the terms of the
569112eddSAli Bahrami  * Common Development and Distribution License (the "License").
669112eddSAli Bahrami  * You may not use this file except in compliance with the License.
769112eddSAli Bahrami  *
869112eddSAli Bahrami  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
969112eddSAli Bahrami  * or http://www.opensolaris.org/os/licensing.
1069112eddSAli Bahrami  * See the License for the specific language governing permissions
1169112eddSAli Bahrami  * and limitations under the License.
1269112eddSAli Bahrami  *
1369112eddSAli Bahrami  * When distributing Covered Code, include this CDDL HEADER in each
1469112eddSAli Bahrami  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1569112eddSAli Bahrami  * If applicable, add the following below this CDDL HEADER, with the
1669112eddSAli Bahrami  * fields enclosed by brackets "[]" replaced with your own identifying
1769112eddSAli Bahrami  * information: Portions Copyright [yyyy] [name of copyright owner]
1869112eddSAli Bahrami  *
1969112eddSAli Bahrami  * CDDL HEADER END
2069112eddSAli Bahrami  */
2169112eddSAli Bahrami 
2269112eddSAli Bahrami /*
2369112eddSAli Bahrami  *	Copyright (c) 1988 AT&T
2469112eddSAli Bahrami  *	  All Rights Reserved
2569112eddSAli Bahrami  *
261007fd6fSAli Bahrami  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
2744bf619dSJohn Levon  *
2844bf619dSJohn Levon  * Copyright 2019 Joyent, Inc.
2969112eddSAli Bahrami  */
3069112eddSAli Bahrami 
3169112eddSAli Bahrami /*
3269112eddSAli Bahrami  * Map file parsing (Shared Core Code).
3369112eddSAli Bahrami  */
3469112eddSAli Bahrami #include	<fcntl.h>
3569112eddSAli Bahrami #include	<stdio.h>
3669112eddSAli Bahrami #include	<unistd.h>
3769112eddSAli Bahrami #include	<sys/stat.h>
3869112eddSAli Bahrami #include	<errno.h>
3969112eddSAli Bahrami #include	<limits.h>
4069112eddSAli Bahrami #include	<dirent.h>
4169112eddSAli Bahrami #include	<ctype.h>
4269112eddSAli Bahrami #include	<debug.h>
4369112eddSAli Bahrami #include	"msg.h"
4469112eddSAli Bahrami #include	"_libld.h"
4569112eddSAli Bahrami #include	"_map.h"
4669112eddSAli Bahrami 
4769112eddSAli Bahrami /*
4869112eddSAli Bahrami  * There are two styles of mapfile supported by the link-editor:
4969112eddSAli Bahrami  *
5069112eddSAli Bahrami  * 1)	The original System V defined syntax, as augmented at Sun
5169112eddSAli Bahrami  *	from Solaris 2.0 through Solaris 10. This style is also known
5269112eddSAli Bahrami  *	as version 1.
5369112eddSAli Bahrami  *
5469112eddSAli Bahrami  * 2)	A newer syntax, currently at version 2.
5569112eddSAli Bahrami  *
5669112eddSAli Bahrami  * The original syntax uses special characters (=, :, -, |, etc) as
5769112eddSAli Bahrami  * operators to indicate the operation being specified. Over the years,
5869112eddSAli Bahrami  * this syntax has been problematic:
5969112eddSAli Bahrami  *
6069112eddSAli Bahrami  * 1)	Too cryptic: It's hard for people to remember which character
6169112eddSAli Bahrami  *	means what.
6269112eddSAli Bahrami  *
6369112eddSAli Bahrami  * 2)	Limited expansion potential: There only a few special characters
6469112eddSAli Bahrami  *	available on the keyboard for new features, and it is difficult to
6569112eddSAli Bahrami  *	add options to existing ones.
6669112eddSAli Bahrami  *
6769112eddSAli Bahrami  * Adding new features into this framework (2) have the effect of
6869112eddSAli Bahrami  * making the syntax even more cryptic (1). The newer syntax addresses
6969112eddSAli Bahrami  * these issues by moving to an extendible identifier based syntax that
7069112eddSAli Bahrami  * allows new features to be added without complicating old ones.
7169112eddSAli Bahrami  *
7269112eddSAli Bahrami  * The new syntax uses the following terminology:
7369112eddSAli Bahrami  *
7469112eddSAli Bahrami  * -	Control directives are the directives that start with a '$'.
7569112eddSAli Bahrami  *	They control how the mapfile is interpreted. We use the 'cdir_'
7669112eddSAli Bahrami  *	prefix on functions and variables related to these directives.
7769112eddSAli Bahrami  *
7869112eddSAli Bahrami  * -	Conditional Expressions are the expressions found in $if and $elif
7969112eddSAli Bahrami  *	control directives. They evaluate to boolean true/false values.
8069112eddSAli Bahrami  *	We use the 'cexp_' prefix for functions and variables related to
8169112eddSAli Bahrami  *	these expressions.
8269112eddSAli Bahrami  *
8369112eddSAli Bahrami  * -	Regular Directives are names (SYMBOL, VERSION, etc) that convey
8469112eddSAli Bahrami  *	directions to the link-editor for building the output object.
8569112eddSAli Bahrami  *
8669112eddSAli Bahrami  * This file contains core code used by both mapfile styles: File management,
8769112eddSAli Bahrami  * lexical analysis, and other shared core functionality. It also contains
8869112eddSAli Bahrami  * the code for control directives, as they are intrinsically part of
8969112eddSAli Bahrami  * lexical analysis --- this is disabled when processing Sysv mapfiles.
9069112eddSAli Bahrami  */
9169112eddSAli Bahrami 
9269112eddSAli Bahrami /*
9369112eddSAli Bahrami  * We use a stack of cdir_level_t structs to manage $if/$elif/$else/$endif
9469112eddSAli Bahrami  * processing. At each level, we keep track of the information needed to
9569112eddSAli Bahrami  * determine whether or not to process nested input lines or skip them,
9669112eddSAli Bahrami  * along with information needed to report errors.
9769112eddSAli Bahrami  */
9869112eddSAli Bahrami typedef struct {
9969112eddSAli Bahrami 	Lineno		cdl_if_lineno;	/* Line number of opening $if */
10069112eddSAli Bahrami 	Lineno		cdl_else_lineno; /* 0, or line on which $else seen */
10169112eddSAli Bahrami 	int		cdl_done;	/* True if no longer accepts input */
10269112eddSAli Bahrami 	int		cdl_pass;	/* True if currently accepting input */
10369112eddSAli Bahrami } cdir_level_t;
10469112eddSAli Bahrami 
10569112eddSAli Bahrami /* Operators in the expressions accepted by $if/$elif */
10669112eddSAli Bahrami typedef enum {
10769112eddSAli Bahrami 	CEXP_OP_NONE,		/* Not an operator */
10869112eddSAli Bahrami 	CEXP_OP_AND,		/* && */
10969112eddSAli Bahrami 	CEXP_OP_OR,		/* || */
11069112eddSAli Bahrami 	CEXP_OP_NEG,		/* ! */
11169112eddSAli Bahrami 	CEXP_OP_OPAR,		/* ( */
11269112eddSAli Bahrami 	CEXP_OP_CPAR		/* ) */
11369112eddSAli Bahrami } cexp_op_t;
11469112eddSAli Bahrami 
11569112eddSAli Bahrami /*
11669112eddSAli Bahrami  * Type of conditional expression identifier AVL tree nodes
11769112eddSAli Bahrami  */
11869112eddSAli Bahrami typedef struct cexp_name_node {
11969112eddSAli Bahrami 	avl_node_t	ceid_avlnode;	/* AVL book-keeping */
12069112eddSAli Bahrami 	const char	*ceid_name;	/* boolean identifier name */
12169112eddSAli Bahrami } cexp_id_node_t;
12269112eddSAli Bahrami 
12369112eddSAli Bahrami 
12469112eddSAli Bahrami /*
12569112eddSAli Bahrami  * Declare a "stack" type, containing a pointer to data, a count of
12669112eddSAli Bahrami  * allocated, and currently used items in the stack. The data type
12769112eddSAli Bahrami  * is specified as the _type argument.
12869112eddSAli Bahrami  */
12969112eddSAli Bahrami #define	STACK(_type) \
13069112eddSAli Bahrami 	struct { \
13169112eddSAli Bahrami 		_type	*stk_s;		/* Stack array */ \
13269112eddSAli Bahrami 		size_t	stk_n;		/* Current stack depth */ \
13369112eddSAli Bahrami 		size_t	stk_n_alloc;	/* # of elements pointed at by s */ \
13469112eddSAli Bahrami 	}
13569112eddSAli Bahrami 
13669112eddSAli Bahrami /*
13769112eddSAli Bahrami  * The following type represents a "generic" stack, where the data
13869112eddSAli Bahrami  * type is (void). This type is never instantiated. However, it has
13969112eddSAli Bahrami  * the same struct layout as any other STACK(), and is therefore a good
14069112eddSAli Bahrami  * generic type that can be used for stack_resize().
14169112eddSAli Bahrami  */
14269112eddSAli Bahrami typedef STACK(void) generic_stack_t;
14369112eddSAli Bahrami 
14469112eddSAli Bahrami /*
14569112eddSAli Bahrami  * Ensure that the stack has enough room to push one more item
14669112eddSAli Bahrami  */
14769112eddSAli Bahrami #define	STACK_RESERVE(_stack, _n_default) \
14869112eddSAli Bahrami 	(((_stack).stk_n < (_stack).stk_n_alloc) || \
14969112eddSAli Bahrami 	stack_resize((generic_stack_t *)&(_stack).stk_s, _n_default, \
15069112eddSAli Bahrami 	sizeof (*(_stack).stk_s)))
15169112eddSAli Bahrami 
15269112eddSAli Bahrami /*
15369112eddSAli Bahrami  * Reset a stack to empty.
15469112eddSAli Bahrami  */
15569112eddSAli Bahrami #define	STACK_RESET(_stack) (_stack).stk_n = 0;
15669112eddSAli Bahrami 
15769112eddSAli Bahrami /*
15869112eddSAli Bahrami  * True if stack is empty, False otherwise.
15969112eddSAli Bahrami  */
16069112eddSAli Bahrami #define	STACK_IS_EMPTY(_stack) ((_stack).stk_n == 0)
16169112eddSAli Bahrami 
16269112eddSAli Bahrami /*
16369112eddSAli Bahrami  * Push a value onto a stack. Caller must ensure that stack has room.
16469112eddSAli Bahrami  * This macro is intended to be used as the LHS of an assignment, the
16569112eddSAli Bahrami  * RHS of which is the value:
16669112eddSAli Bahrami  *
16769112eddSAli Bahrami  *	STACK_PUSH(stack) = value;
16869112eddSAli Bahrami  */
16969112eddSAli Bahrami #define	STACK_PUSH(_stack) (_stack).stk_s[(_stack).stk_n++]
17069112eddSAli Bahrami 
17169112eddSAli Bahrami /*
17269112eddSAli Bahrami  * Pop a value off a stack.  Caller must ensure
17369112eddSAli Bahrami  * that stack is not empty.
17469112eddSAli Bahrami  */
17569112eddSAli Bahrami #define	STACK_POP(_stack) ((_stack).stk_s[--(_stack).stk_n])
17669112eddSAli Bahrami 
17769112eddSAli Bahrami /*
17869112eddSAli Bahrami  * Access top element on stack without popping. Caller must ensure
17969112eddSAli Bahrami  * that stack is not empty.
18069112eddSAli Bahrami  */
18169112eddSAli Bahrami #define	STACK_TOP(_stack) (((_stack).stk_s)[(_stack).stk_n - 1])
18269112eddSAli Bahrami 
18369112eddSAli Bahrami /*
18469112eddSAli Bahrami  * Initial sizes used for the stacks: The stacks are allocated on demand
18569112eddSAli Bahrami  * to these sizes, and then doubled as necessary until they are large enough.
18669112eddSAli Bahrami  *
18769112eddSAli Bahrami  * The ideal size would be large enough that only a single allocation
18869112eddSAli Bahrami  * occurs, and our defaults should generally have that effect. However,
18969112eddSAli Bahrami  * in doing so, we run the risk of a latent error in the resize code going
19069112eddSAli Bahrami  * undetected until triggered by a large task in the field. For this reason,
19169112eddSAli Bahrami  * we set the sizes to the smallest size possible when compiled for debug.
19269112eddSAli Bahrami  */
19369112eddSAli Bahrami #ifdef DEBUG
19469112eddSAli Bahrami #define	CDIR_STACK_INIT		1
19569112eddSAli Bahrami #define	CEXP_OP_STACK_INIT	1
19669112eddSAli Bahrami #define	CEXP_VAL_STACK_INIT	1
19769112eddSAli Bahrami #else
1988222814eSRichard Lowe #define	CDIR_STACK_INIT		16
19969112eddSAli Bahrami #define	CEXP_OP_STACK_INIT	8
20069112eddSAli Bahrami #define	CEXP_VAL_STACK_INIT	(CEXP_OP_STACK_INIT * 2) /* 2 vals per binop */
20169112eddSAli Bahrami #endif
20269112eddSAli Bahrami 
20369112eddSAli Bahrami 
20469112eddSAli Bahrami /*
20569112eddSAli Bahrami  * Persistent state maintained by map module in between calls.
20669112eddSAli Bahrami  *
20769112eddSAli Bahrami  * This is kept as static file scope data, because it is only used
20869112eddSAli Bahrami  * when libld is called by ld, and not by rtld. If that should change,
20969112eddSAli Bahrami  * the code is designed so that it can become reentrant easily:
21069112eddSAli Bahrami  *
21169112eddSAli Bahrami  * -	Add a pointer to the output descriptor to a structure of this type,
21269112eddSAli Bahrami  *	allocated dynamically on the first call to ld_map_parse().
21369112eddSAli Bahrami  * -	Change all references to lms to instead reference the pointer in
21469112eddSAli Bahrami  *	the output descriptor.
21569112eddSAli Bahrami  *
21669112eddSAli Bahrami  * Until then, it is simpler not to expose these details.
21769112eddSAli Bahrami  */
21869112eddSAli Bahrami typedef struct {
21969112eddSAli Bahrami 	int	lms_cdir_valid;	/* Allow control dir. on entry to gettoken() */
22069112eddSAli Bahrami 	STACK(cdir_level_t)	lms_cdir_stack;	/* Conditional input level */
22169112eddSAli Bahrami 	STACK(cexp_op_t)	lms_cexp_op_stack; /* Cond. expr operators */
22269112eddSAli Bahrami 	STACK(uchar_t)		lms_cexp_val_stack; /* Cond. expr values */
22369112eddSAli Bahrami 	avl_tree_t		*lms_cexp_id;
22469112eddSAli Bahrami } ld_map_state_t;
22569112eddSAli Bahrami static ld_map_state_t lms;
22669112eddSAli Bahrami 
22769112eddSAli Bahrami 
22869112eddSAli Bahrami /*
22969112eddSAli Bahrami  * Version 1 (SysV) syntax dispatch table for ld_map_gettoken(). For each
23069112eddSAli Bahrami  * of the 7-bit ASCII characters, determine how the lexical analyzer
23169112eddSAli Bahrami  * should behave.
23269112eddSAli Bahrami  *
23369112eddSAli Bahrami  * This table must be kept in sync with tkid_attr[] below.
23469112eddSAli Bahrami  *
23569112eddSAli Bahrami  * Identifier Note:
23669112eddSAli Bahrami  * The Linker and Libraries Guide states that the original syntax uses
23769112eddSAli Bahrami  * C identifier rules, allowing '.' to be treated as a letter. However,
23869112eddSAli Bahrami  * the implementation is considerably looser than that: Any character
23969112eddSAli Bahrami  * with an ASCII code (0-127) which is printable and not used to start
24069112eddSAli Bahrami  * another token is allowed to start an identifier, and they are terminated
24169112eddSAli Bahrami  * by any of: space, double quote, tab, newline, ':', ';', '=', or '#'.
24269112eddSAli Bahrami  * The original code has been replaced, but this table encodes the same
24369112eddSAli Bahrami  * rules, to ensure backward compatibility.
24469112eddSAli Bahrami  */
24569112eddSAli Bahrami static const mf_tokdisp_t gettok_dispatch_v1 = {
24669112eddSAli Bahrami 	TK_OP_EOF,			/* 0 - NUL */
24769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 1 - SOH */
24869112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 2 - STX */
24969112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 3 - ETX */
25069112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 4 - EOT */
25169112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 5 - ENQ */
25269112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 6 - ACK */
25369112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 7 - BEL */
25469112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 8 - BS */
25569112eddSAli Bahrami 	TK_OP_WS,			/* 9 - HT */
25669112eddSAli Bahrami 	TK_OP_NL,			/* 10 - NL */
25769112eddSAli Bahrami 	TK_OP_WS,			/* 11 - VT */
25869112eddSAli Bahrami 	TK_OP_WS,			/* 12 - FF */
25969112eddSAli Bahrami 	TK_OP_WS,			/* 13 - CR */
26069112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 14 - SO */
26169112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 15 - SI */
26269112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 16 - DLE */
26369112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 17 - DC1 */
26469112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 18 - DC2 */
26569112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 19 - DC3 */
26669112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 20 - DC4 */
26769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 21 - NAK */
26869112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 22 - SYN */
26969112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 23 - ETB */
27069112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 24 - CAN */
27169112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 25 - EM */
27269112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 26 - SUB */
27369112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 27 - ESC */
27469112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 28 - FS */
27569112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 29 - GS */
27669112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 30 - RS */
27769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 31 - US */
27869112eddSAli Bahrami 	TK_OP_WS,			/* 32 - SP */
27969112eddSAli Bahrami 	TK_OP_ID,			/* 33 - ! */
28069112eddSAli Bahrami 	TK_OP_SIMQUOTE,			/* 34 - " */
28169112eddSAli Bahrami 	TK_OP_CMT,			/* 35 - # */
28269112eddSAli Bahrami 	TK_OP_ID,			/* 36 - $ */
28369112eddSAli Bahrami 	TK_OP_ID,			/* 37 - % */
28469112eddSAli Bahrami 	TK_OP_ID,			/* 38 - & */
28569112eddSAli Bahrami 	TK_OP_ID,			/* 39 - ' */
28669112eddSAli Bahrami 	TK_OP_ID,			/* 40 - ( */
28769112eddSAli Bahrami 	TK_OP_ID,			/* 41 - ) */
28869112eddSAli Bahrami 	TK_OP_ID,			/* 42 - * */
28969112eddSAli Bahrami 	TK_OP_ID,			/* 43 - + */
29069112eddSAli Bahrami 	TK_OP_ID,			/* 44 - , */
29169112eddSAli Bahrami 	TK_DASH,			/* 45 - - */
29269112eddSAli Bahrami 	TK_OP_ID,			/* 46 - . */
29369112eddSAli Bahrami 	TK_OP_ID,			/* 47 - / */
29469112eddSAli Bahrami 	TK_OP_ID,			/* 48 - 0 */
29569112eddSAli Bahrami 	TK_OP_ID,			/* 49 - 1 */
29669112eddSAli Bahrami 	TK_OP_ID,			/* 50 - 2 */
29769112eddSAli Bahrami 	TK_OP_ID,			/* 51 - 3 */
29869112eddSAli Bahrami 	TK_OP_ID,			/* 52 - 4 */
29969112eddSAli Bahrami 	TK_OP_ID,			/* 53 - 5 */
30069112eddSAli Bahrami 	TK_OP_ID,			/* 54 - 6 */
30169112eddSAli Bahrami 	TK_OP_ID,			/* 55 - 7 */
30269112eddSAli Bahrami 	TK_OP_ID,			/* 56 - 8 */
30369112eddSAli Bahrami 	TK_OP_ID,			/* 57 - 9 */
30469112eddSAli Bahrami 	TK_COLON,			/* 58 - : */
30569112eddSAli Bahrami 	TK_SEMICOLON,			/* 59 - ; */
30669112eddSAli Bahrami 	TK_OP_ID,			/* 60 - < */
30769112eddSAli Bahrami 	TK_EQUAL,			/* 61 - = */
30869112eddSAli Bahrami 	TK_OP_ID,			/* 62 - > */
30969112eddSAli Bahrami 	TK_OP_ID,			/* 63 - ? */
31069112eddSAli Bahrami 	TK_ATSIGN,			/* 64 - @ */
31169112eddSAli Bahrami 	TK_OP_ID,			/* 65 - A */
31269112eddSAli Bahrami 	TK_OP_ID,			/* 66 - B */
31369112eddSAli Bahrami 	TK_OP_ID,			/* 67 - C */
31469112eddSAli Bahrami 	TK_OP_ID,			/* 68 - D */
31569112eddSAli Bahrami 	TK_OP_ID,			/* 69 - E */
31669112eddSAli Bahrami 	TK_OP_ID,			/* 70 - F */
31769112eddSAli Bahrami 	TK_OP_ID,			/* 71 - G */
31869112eddSAli Bahrami 	TK_OP_ID,			/* 72 - H */
31969112eddSAli Bahrami 	TK_OP_ID,			/* 73 - I */
32069112eddSAli Bahrami 	TK_OP_ID,			/* 74 - J */
32169112eddSAli Bahrami 	TK_OP_ID,			/* 75 - K */
32269112eddSAli Bahrami 	TK_OP_ID,			/* 76 - L */
32369112eddSAli Bahrami 	TK_OP_ID,			/* 77 - M */
32469112eddSAli Bahrami 	TK_OP_ID,			/* 78 - N */
32569112eddSAli Bahrami 	TK_OP_ID,			/* 79 - O */
32669112eddSAli Bahrami 	TK_OP_ID,			/* 80 - P */
32769112eddSAli Bahrami 	TK_OP_ID,			/* 81 - Q */
32869112eddSAli Bahrami 	TK_OP_ID,			/* 82 - R */
32969112eddSAli Bahrami 	TK_OP_ID,			/* 83 - S */
33069112eddSAli Bahrami 	TK_OP_ID,			/* 84 - T */
33169112eddSAli Bahrami 	TK_OP_ID,			/* 85 - U */
33269112eddSAli Bahrami 	TK_OP_ID,			/* 86 - V */
33369112eddSAli Bahrami 	TK_OP_ID,			/* 87 - W */
33469112eddSAli Bahrami 	TK_OP_ID,			/* 88 - X */
33569112eddSAli Bahrami 	TK_OP_ID,			/* 89 - Y */
33669112eddSAli Bahrami 	TK_OP_ID,			/* 90 - Z */
33769112eddSAli Bahrami 	TK_OP_ID,			/* 91 - [ */
33869112eddSAli Bahrami 	TK_OP_ID,			/* 92 - \ */
33969112eddSAli Bahrami 	TK_OP_ID,			/* 93 - ] */
34069112eddSAli Bahrami 	TK_OP_ID,			/* 94 - ^ */
34169112eddSAli Bahrami 	TK_OP_ID,			/* 95 - _ */
34269112eddSAli Bahrami 	TK_OP_ID,			/* 96 - ` */
34369112eddSAli Bahrami 	TK_OP_ID,			/* 97 - a */
34469112eddSAli Bahrami 	TK_OP_ID,			/* 98 - b */
34569112eddSAli Bahrami 	TK_OP_ID,			/* 99 - c */
34669112eddSAli Bahrami 	TK_OP_ID,			/* 100 - d */
34769112eddSAli Bahrami 	TK_OP_ID,			/* 101 - e */
34869112eddSAli Bahrami 	TK_OP_ID,			/* 102 - f */
34969112eddSAli Bahrami 	TK_OP_ID,			/* 103 - g */
35069112eddSAli Bahrami 	TK_OP_ID,			/* 104 - h */
35169112eddSAli Bahrami 	TK_OP_ID,			/* 105 - i */
35269112eddSAli Bahrami 	TK_OP_ID,			/* 106 - j */
35369112eddSAli Bahrami 	TK_OP_ID,			/* 107 - k */
35469112eddSAli Bahrami 	TK_OP_ID,			/* 108 - l */
35569112eddSAli Bahrami 	TK_OP_ID,			/* 109 - m */
35669112eddSAli Bahrami 	TK_OP_ID,			/* 110 - n */
35769112eddSAli Bahrami 	TK_OP_ID,			/* 111 - o */
35869112eddSAli Bahrami 	TK_OP_ID,			/* 112 - p */
35969112eddSAli Bahrami 	TK_OP_ID,			/* 113 - q */
36069112eddSAli Bahrami 	TK_OP_ID,			/* 114 - r */
36169112eddSAli Bahrami 	TK_OP_ID,			/* 115 - s */
36269112eddSAli Bahrami 	TK_OP_ID,			/* 116 - t */
36369112eddSAli Bahrami 	TK_OP_ID,			/* 117 - u */
36469112eddSAli Bahrami 	TK_OP_ID,			/* 118 - v */
36569112eddSAli Bahrami 	TK_OP_ID,			/* 119 - w */
36669112eddSAli Bahrami 	TK_OP_ID,			/* 120 - x */
36769112eddSAli Bahrami 	TK_OP_ID,			/* 121 - y */
36869112eddSAli Bahrami 	TK_OP_ID,			/* 122 - z */
36969112eddSAli Bahrami 	TK_LEFTBKT,			/* 123 - { */
37069112eddSAli Bahrami 	TK_PIPE,			/* 124 - | */
37169112eddSAli Bahrami 	TK_RIGHTBKT,			/* 125 - } */
37269112eddSAli Bahrami 	TK_OP_ID,			/* 126 - ~ */
37369112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 127 - DEL */
37469112eddSAli Bahrami };
37569112eddSAli Bahrami 
37669112eddSAli Bahrami /*
37769112eddSAli Bahrami  * Version 2 syntax dispatch table for ld_map_gettoken(). For each of the
37869112eddSAli Bahrami  * 7-bit ASCII characters, determine how the lexical analyzer should behave.
37969112eddSAli Bahrami  *
38069112eddSAli Bahrami  * This table must be kept in sync with tkid_attr[] below.
38169112eddSAli Bahrami  *
38269112eddSAli Bahrami  * Identifier Note:
38369112eddSAli Bahrami  * We define a letter as being one of the character [A-Z], [a-z], or [_%/.]
38469112eddSAli Bahrami  * A digit is the numbers [0-9], or [$-]. An unquoted identifier is defined
38569112eddSAli Bahrami  * as a letter, followed by any number of letters or digits. This is a loosened
38669112eddSAli Bahrami  * version of the C definition of an identifier. The extra characters not
38769112eddSAli Bahrami  * allowed by C are common in section names and/or file paths.
38869112eddSAli Bahrami  */
38969112eddSAli Bahrami static const mf_tokdisp_t gettok_dispatch_v2 = {
39069112eddSAli Bahrami 	TK_OP_EOF,			/* 0 - NUL */
39169112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 1 - SOH */
39269112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 2 - STX */
39369112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 3 - ETX */
39469112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 4 - EOT */
39569112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 5 - ENQ */
39669112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 6 - ACK */
39769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 7 - BEL */
39869112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 8 - BS */
39969112eddSAli Bahrami 	TK_OP_WS,			/* 9 - HT */
40069112eddSAli Bahrami 	TK_OP_NL,			/* 10 - NL */
40169112eddSAli Bahrami 	TK_OP_WS,			/* 11 - VT */
40269112eddSAli Bahrami 	TK_OP_WS,			/* 12 - FF */
40369112eddSAli Bahrami 	TK_OP_WS,			/* 13 - CR */
40469112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 14 - SO */
40569112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 15 - SI */
40669112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 16 - DLE */
40769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 17 - DC1 */
40869112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 18 - DC2 */
40969112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 19 - DC3 */
41069112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 20 - DC4 */
41169112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 21 - NAK */
41269112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 22 - SYN */
41369112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 23 - ETB */
41469112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 24 - CAN */
41569112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 25 - EM */
41669112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 26 - SUB */
41769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 27 - ESC */
41869112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 28 - FS */
41969112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 29 - GS */
42069112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 30 - RS */
42169112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 31 - US */
42269112eddSAli Bahrami 	TK_OP_WS,			/* 32 - SP */
42369112eddSAli Bahrami 	TK_BANG,			/* 33 - ! */
42469112eddSAli Bahrami 	TK_OP_CQUOTE,			/* 34 - " */
42569112eddSAli Bahrami 	TK_OP_CMT,			/* 35 - # */
42669112eddSAli Bahrami 	TK_OP_CDIR,			/* 36 - $ */
42769112eddSAli Bahrami 	TK_OP_ID,			/* 37 - % */
42869112eddSAli Bahrami 	TK_OP_BADCHR,			/* 38 - & */
42969112eddSAli Bahrami 	TK_OP_SIMQUOTE,			/* 39 - ' */
43069112eddSAli Bahrami 	TK_OP_BADCHR,			/* 40 - ( */
43169112eddSAli Bahrami 	TK_OP_BADCHR,			/* 41 - ) */
43269112eddSAli Bahrami 	TK_STAR,			/* 42 - * */
43369112eddSAli Bahrami 	TK_OP_CEQUAL,			/* 43 - + */
43469112eddSAli Bahrami 	TK_OP_BADCHR,			/* 44 - , */
43569112eddSAli Bahrami 	TK_OP_CEQUAL,			/* 45 - - */
43669112eddSAli Bahrami 	TK_OP_ID,			/* 46 - . */
43769112eddSAli Bahrami 	TK_OP_ID,			/* 47 - / */
43869112eddSAli Bahrami 	TK_OP_NUM,			/* 48 - 0 */
43969112eddSAli Bahrami 	TK_OP_NUM,			/* 49 - 1 */
44069112eddSAli Bahrami 	TK_OP_NUM,			/* 50 - 2 */
44169112eddSAli Bahrami 	TK_OP_NUM,			/* 51 - 3 */
44269112eddSAli Bahrami 	TK_OP_NUM,			/* 52 - 4 */
44369112eddSAli Bahrami 	TK_OP_NUM,			/* 53 - 5 */
44469112eddSAli Bahrami 	TK_OP_NUM,			/* 54 - 6 */
44569112eddSAli Bahrami 	TK_OP_NUM,			/* 55 - 7 */
44669112eddSAli Bahrami 	TK_OP_NUM,			/* 56 - 8 */
44769112eddSAli Bahrami 	TK_OP_NUM,			/* 57 - 9 */
44869112eddSAli Bahrami 	TK_COLON,			/* 58 - : */
44969112eddSAli Bahrami 	TK_SEMICOLON,			/* 59 - ; */
45069112eddSAli Bahrami 	TK_OP_BADCHR,			/* 60 - < */
45169112eddSAli Bahrami 	TK_EQUAL,			/* 61 - = */
45269112eddSAli Bahrami 	TK_OP_BADCHR,			/* 62 - > */
45369112eddSAli Bahrami 	TK_OP_BADCHR,			/* 63 - ? */
45469112eddSAli Bahrami 	TK_OP_BADCHR,			/* 64 - @ */
45569112eddSAli Bahrami 	TK_OP_ID,			/* 65 - A */
45669112eddSAli Bahrami 	TK_OP_ID,			/* 66 - B */
45769112eddSAli Bahrami 	TK_OP_ID,			/* 67 - C */
45869112eddSAli Bahrami 	TK_OP_ID,			/* 68 - D */
45969112eddSAli Bahrami 	TK_OP_ID,			/* 69 - E */
46069112eddSAli Bahrami 	TK_OP_ID,			/* 70 - F */
46169112eddSAli Bahrami 	TK_OP_ID,			/* 71 - G */
46269112eddSAli Bahrami 	TK_OP_ID,			/* 72 - H */
46369112eddSAli Bahrami 	TK_OP_ID,			/* 73 - I */
46469112eddSAli Bahrami 	TK_OP_ID,			/* 74 - J */
46569112eddSAli Bahrami 	TK_OP_ID,			/* 75 - K */
46669112eddSAli Bahrami 	TK_OP_ID,			/* 76 - L */
46769112eddSAli Bahrami 	TK_OP_ID,			/* 77 - M */
46869112eddSAli Bahrami 	TK_OP_ID,			/* 78 - N */
46969112eddSAli Bahrami 	TK_OP_ID,			/* 79 - O */
47069112eddSAli Bahrami 	TK_OP_ID,			/* 80 - P */
47169112eddSAli Bahrami 	TK_OP_ID,			/* 81 - Q */
47269112eddSAli Bahrami 	TK_OP_ID,			/* 82 - R */
47369112eddSAli Bahrami 	TK_OP_ID,			/* 83 - S */
47469112eddSAli Bahrami 	TK_OP_ID,			/* 84 - T */
47569112eddSAli Bahrami 	TK_OP_ID,			/* 85 - U */
47669112eddSAli Bahrami 	TK_OP_ID,			/* 86 - V */
47769112eddSAli Bahrami 	TK_OP_ID,			/* 87 - W */
47869112eddSAli Bahrami 	TK_OP_ID,			/* 88 - X */
47969112eddSAli Bahrami 	TK_OP_ID,			/* 89 - Y */
48069112eddSAli Bahrami 	TK_OP_ID,			/* 90 - Z */
4818222814eSRichard Lowe 	TK_LEFTSQR,			/* 91 - [ */
48269112eddSAli Bahrami 	TK_OP_BADCHR,			/* 92 - \ */
4838222814eSRichard Lowe 	TK_RIGHTSQR,			/* 93 - ] */
48469112eddSAli Bahrami 	TK_OP_BADCHR,			/* 94 - ^ */
48569112eddSAli Bahrami 	TK_OP_ID,			/* 95 - _ */
48669112eddSAli Bahrami 	TK_OP_BADCHR,			/* 96 - ` */
48769112eddSAli Bahrami 	TK_OP_ID,			/* 97 - a */
48869112eddSAli Bahrami 	TK_OP_ID,			/* 98 - b */
48969112eddSAli Bahrami 	TK_OP_ID,			/* 99 - c */
49069112eddSAli Bahrami 	TK_OP_ID,			/* 100 - d */
49169112eddSAli Bahrami 	TK_OP_ID,			/* 101 - e */
49269112eddSAli Bahrami 	TK_OP_ID,			/* 102 - f */
49369112eddSAli Bahrami 	TK_OP_ID,			/* 103 - g */
49469112eddSAli Bahrami 	TK_OP_ID,			/* 104 - h */
49569112eddSAli Bahrami 	TK_OP_ID,			/* 105 - i */
49669112eddSAli Bahrami 	TK_OP_ID,			/* 106 - j */
49769112eddSAli Bahrami 	TK_OP_ID,			/* 107 - k */
49869112eddSAli Bahrami 	TK_OP_ID,			/* 108 - l */
49969112eddSAli Bahrami 	TK_OP_ID,			/* 109 - m */
50069112eddSAli Bahrami 	TK_OP_ID,			/* 110 - n */
50169112eddSAli Bahrami 	TK_OP_ID,			/* 111 - o */
50269112eddSAli Bahrami 	TK_OP_ID,			/* 112 - p */
50369112eddSAli Bahrami 	TK_OP_ID,			/* 113 - q */
50469112eddSAli Bahrami 	TK_OP_ID,			/* 114 - r */
50569112eddSAli Bahrami 	TK_OP_ID,			/* 115 - s */
50669112eddSAli Bahrami 	TK_OP_ID,			/* 116 - t */
50769112eddSAli Bahrami 	TK_OP_ID,			/* 117 - u */
50869112eddSAli Bahrami 	TK_OP_ID,			/* 118 - v */
50969112eddSAli Bahrami 	TK_OP_ID,			/* 119 - w */
51069112eddSAli Bahrami 	TK_OP_ID,			/* 120 - x */
51169112eddSAli Bahrami 	TK_OP_ID,			/* 121 - y */
51269112eddSAli Bahrami 	TK_OP_ID,			/* 122 - z */
51369112eddSAli Bahrami 	TK_LEFTBKT,			/* 123 - { */
51469112eddSAli Bahrami 	TK_OP_BADCHR,			/* 124 - | */
51569112eddSAli Bahrami 	TK_RIGHTBKT,			/* 125 - } */
51669112eddSAli Bahrami 	TK_OP_BADCHR,			/* 126 - ~ */
51769112eddSAli Bahrami 	TK_OP_ILLCHR,			/* 127 - DEL */
51869112eddSAli Bahrami };
51969112eddSAli Bahrami 
52069112eddSAli Bahrami 
52169112eddSAli Bahrami /*
52269112eddSAli Bahrami  * Table used to identify unquoted identifiers. Each element of this array
52369112eddSAli Bahrami  * contains a bitmask indicating whether the character it represents starts,
52469112eddSAli Bahrami  * or continues an identifier, for each supported mapfile syntax version.
52569112eddSAli Bahrami  */
52669112eddSAli Bahrami static const char tkid_attr[128] = {
52769112eddSAli Bahrami 	0,					/* 0 - NUL */
52869112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 1 - SOH */
52969112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 2 - STX */
53069112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 3 - ETX */
53169112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 4 - EOT */
53269112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 5 - ENQ */
53369112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 6 - ACK */
53469112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 7 - BEL */
53569112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 8 - BS */
53669112eddSAli Bahrami 	0,					/* 9 - HT */
53769112eddSAli Bahrami 	0,					/* 10 - NL */
53869112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 11 - VT */
53969112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 12 - FF */
54069112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 13 - CR */
54169112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 14 - SO */
54269112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 15 - SI */
54369112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 16 - DLE */
54469112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 17 - DC1 */
54569112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 18 - DC2 */
54669112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 19 - DC3 */
54769112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 20 - DC4 */
54869112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 21 - NAK */
54969112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 22 - SYN */
55069112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 23 - ETB */
55169112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 24 - CAN */
55269112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 25 - EM */
55369112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 26 - SUB */
55469112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 27 - ESC */
55569112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 28 - FS */
55669112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 29 - GS */
55769112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 30 - RS */
55869112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 31 - US */
55969112eddSAli Bahrami 	0,					/* 32 - SP */
56069112eddSAli Bahrami 	TKID_ATTR(1),				/* 33 - ! */
56169112eddSAli Bahrami 	0,					/* 34 - " */
56269112eddSAli Bahrami 	0,					/* 35 - # */
56369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 36 - $ */
56469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 37 - % */
56569112eddSAli Bahrami 	TKID_ATTR(1),				/* 38 - & */
56669112eddSAli Bahrami 	TKID_ATTR(1),				/* 39 - ' */
56769112eddSAli Bahrami 	TKID_ATTR(1),				/* 40 - ( */
56869112eddSAli Bahrami 	TKID_ATTR(1),				/* 41 - ) */
56969112eddSAli Bahrami 	TKID_ATTR(1),				/* 42 - * */
57069112eddSAli Bahrami 	TKID_ATTR(1),				/* 43 - + */
57169112eddSAli Bahrami 	TKID_ATTR(1),				/* 44 - , */
57269112eddSAli Bahrami 	TKID_ATTR_CONT(1) | TKID_ATTR_CONT(2),	/* 45 - - */
57369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 46 - . */
57469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 47 - / */
57569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 48 - 0 */
57669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 49 - 1 */
57769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 50 - 2 */
57869112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 51 - 3 */
57969112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 52 - 4 */
58069112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 53 - 5 */
58169112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 54 - 6 */
58269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 55 - 7 */
58369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 56 - 8 */
58469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR_CONT(2),	/* 57 - 9 */
58569112eddSAli Bahrami 	0,					/* 58 - : */
58669112eddSAli Bahrami 	0,					/* 59 - ; */
58769112eddSAli Bahrami 	TKID_ATTR(1),				/* 60 - < */
58869112eddSAli Bahrami 	0,					/* 61 - = */
58969112eddSAli Bahrami 	TKID_ATTR(1),				/* 62 - > */
59069112eddSAli Bahrami 	TKID_ATTR(1),				/* 63 - ? */
59169112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 64 - @ */
59269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 65 - A */
59369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 66 - B */
59469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 67 - C */
59569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 68 - D */
59669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 69 - E */
59769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 70 - F */
59869112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 71 - G */
59969112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 72 - H */
60069112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 73 - I */
60169112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 74 - J */
60269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 75 - K */
60369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 76 - L */
60469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 77 - M */
60569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 78 - N */
60669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 79 - O */
60769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 80 - P */
60869112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 81 - Q */
60969112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 82 - R */
61069112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 83 - S */
61169112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 84 - T */
61269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 85 - U */
61369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 86 - V */
61469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 87 - W */
61569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 88 - X */
61669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 89 - Y */
61769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 90 - Z */
61869112eddSAli Bahrami 	TKID_ATTR(1),				/* 91 - [ */
61969112eddSAli Bahrami 	TKID_ATTR(1),				/* 92 - \ */
62069112eddSAli Bahrami 	TKID_ATTR(1),				/* 93 - ] */
62169112eddSAli Bahrami 	TKID_ATTR(1),				/* 94 - ^ */
62269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 95 - _ */
62369112eddSAli Bahrami 	TKID_ATTR(1),				/* 96 - ` */
62469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 97 - a */
62569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 98 - b */
62669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 99 - c */
62769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 100 - d */
62869112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 101 - e */
62969112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 102 - f */
63069112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 103 - g */
63169112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 104 - h */
63269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 105 - i */
63369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 106 - j */
63469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 107 - k */
63569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 108 - l */
63669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 109 - m */
63769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 110 - n */
63869112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 111 - o */
63969112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 112 - p */
64069112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 113 - q */
64169112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 114 - r */
64269112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 115 - s */
64369112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 116 - t */
64469112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 117 - u */
64569112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 118 - v */
64669112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 119 - w */
64769112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 120 - x */
64869112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 121 - y */
64969112eddSAli Bahrami 	TKID_ATTR(1) | TKID_ATTR(2),		/* 122 - z */
65069112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 123 - { */
65169112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 124 - | */
65269112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 125 - } */
65369112eddSAli Bahrami 	TKID_ATTR(1),				/* 126 - ~ */
65469112eddSAli Bahrami 	TKID_ATTR_CONT(1),			/* 127 - DEL */
65569112eddSAli Bahrami };
65669112eddSAli Bahrami 
65769112eddSAli Bahrami 
65869112eddSAli Bahrami /*
65969112eddSAli Bahrami  * Advance the given string pointer to the next newline character,
66069112eddSAli Bahrami  * or the terminating NULL if there is none.
66169112eddSAli Bahrami  */
66269112eddSAli Bahrami inline static void
advance_to_eol(char ** str)66369112eddSAli Bahrami advance_to_eol(char **str)
66469112eddSAli Bahrami {
66569112eddSAli Bahrami 	char	*s = *str;
66669112eddSAli Bahrami 
66769112eddSAli Bahrami 	while ((*s != '\n') && (*s != '\0'))
66869112eddSAli Bahrami 		s++;
66969112eddSAli Bahrami 	*str = s;
67069112eddSAli Bahrami }
67169112eddSAli Bahrami 
67269112eddSAli Bahrami /*
67369112eddSAli Bahrami  * Insert a NULL patch at the given address
67469112eddSAli Bahrami  */
67569112eddSAli Bahrami inline static void
null_patch_set(char * str,ld_map_npatch_t * np)67669112eddSAli Bahrami null_patch_set(char *str, ld_map_npatch_t *np)
67769112eddSAli Bahrami {
67869112eddSAli Bahrami 	np->np_ptr = str;
67969112eddSAli Bahrami 	np->np_ch = *str;
68069112eddSAli Bahrami 	*str = '\0';
68169112eddSAli Bahrami }
68269112eddSAli Bahrami 
68369112eddSAli Bahrami /*
68469112eddSAli Bahrami  * Undo a NULL patch
68569112eddSAli Bahrami  */
68669112eddSAli Bahrami inline static void
null_patch_undo(ld_map_npatch_t * np)68769112eddSAli Bahrami null_patch_undo(ld_map_npatch_t *np)
68869112eddSAli Bahrami {
68969112eddSAli Bahrami 	*np->np_ptr = np->np_ch;
69069112eddSAli Bahrami }
69169112eddSAli Bahrami 
69269112eddSAli Bahrami /*
69369112eddSAli Bahrami  * Insert a NULL patch at the end of the line containing str.
69469112eddSAli Bahrami  */
69569112eddSAli Bahrami static void
null_patch_eol(char * str,ld_map_npatch_t * np)69669112eddSAli Bahrami null_patch_eol(char *str, ld_map_npatch_t *np)
69769112eddSAli Bahrami {
69869112eddSAli Bahrami 	advance_to_eol(&str);
69969112eddSAli Bahrami 	null_patch_set(str, np);
70069112eddSAli Bahrami }
70169112eddSAli Bahrami 
70269112eddSAli Bahrami /*
70369112eddSAli Bahrami  * Locate the end of an unquoted identifier.
70469112eddSAli Bahrami  *
70569112eddSAli Bahrami  * entry:
70669112eddSAli Bahrami  *	mf - Mapfile descriptor, positioned to first character
70769112eddSAli Bahrami  *		of identifier.
70869112eddSAli Bahrami  *
70969112eddSAli Bahrami  * exit:
71069112eddSAli Bahrami  *	If the item pointed at by mf is not an identifier, returns NULL.
71169112eddSAli Bahrami  *	Otherwise, returns pointer to character after the last character
71269112eddSAli Bahrami  *	of the identifier.
71369112eddSAli Bahrami  */
71469112eddSAli Bahrami inline static char *
ident_delimit(Mapfile * mf)71569112eddSAli Bahrami ident_delimit(Mapfile *mf)
71669112eddSAli Bahrami {
71769112eddSAli Bahrami 	char		*str = mf->mf_next;
71869112eddSAli Bahrami 	ld_map_npatch_t	np;
71969112eddSAli Bahrami 	int		c = *str++;
72069112eddSAli Bahrami 
72169112eddSAli Bahrami 	/* If not a valid start character, report the error */
72269112eddSAli Bahrami 	if ((c & 0x80) || !(tkid_attr[c] & mf->mf_tkid_start)) {
72369112eddSAli Bahrami 		null_patch_set(str, &np);
72469112eddSAli Bahrami 		mf_fatal(mf, MSG_INTL(MSG_MAP_BADCHAR), str);
72569112eddSAli Bahrami 		null_patch_undo(&np);
72669112eddSAli Bahrami 		return (NULL);
72769112eddSAli Bahrami 	}
72869112eddSAli Bahrami 
72969112eddSAli Bahrami 	/* Keep going until we hit a non-continuing character */
73069112eddSAli Bahrami 	for (c = *str; !(c & 0x80) && (tkid_attr[c] & mf->mf_tkid_cont);
73169112eddSAli Bahrami 	    c = *++str)
73269112eddSAli Bahrami 		;
73369112eddSAli Bahrami 
73469112eddSAli Bahrami 	return (str);
73569112eddSAli Bahrami }
73669112eddSAli Bahrami 
73769112eddSAli Bahrami /*
73869112eddSAli Bahrami  * Allocate memory for a stack.
73969112eddSAli Bahrami  *
74069112eddSAli Bahrami  * entry:
74169112eddSAli Bahrami  *	stack - Pointer to stack for which memory is required, cast
74269112eddSAli Bahrami  *		to the generic stack type.
74369112eddSAli Bahrami  *	n_default - Size to use for initial allocation.
74469112eddSAli Bahrami  *	elt_size - sizeof(elt), where elt is the actual stack data type.
74569112eddSAli Bahrami  *
74669112eddSAli Bahrami  * exit:
74769112eddSAli Bahrami  *	Returns (1) on success. On error (memory allocation), a message
74869112eddSAli Bahrami  *	is printed and False (0) is returned.
74969112eddSAli Bahrami  *
75069112eddSAli Bahrami  * note:
75169112eddSAli Bahrami  *	The caller casts the pointer to their actual datatype-specific stack
75269112eddSAli Bahrami  *	to be a (generic_stack_t *). The C language will give all stack
75369112eddSAli Bahrami  *	structs the same size and layout as long as the underlying platform
75469112eddSAli Bahrami  *	uses a single integral type for pointers. Hence, this cast is safe,
75569112eddSAli Bahrami  *	and lets a generic routine modify data-specific types without being
75669112eddSAli Bahrami  *	aware of those types.
75769112eddSAli Bahrami  */
75869112eddSAli Bahrami static Boolean
stack_resize(generic_stack_t * stack,size_t n_default,size_t elt_size)75969112eddSAli Bahrami stack_resize(generic_stack_t *stack, size_t n_default, size_t elt_size)
76069112eddSAli Bahrami {
76169112eddSAli Bahrami 	size_t	new_n_alloc;
76269112eddSAli Bahrami 	void	*newaddr;
76369112eddSAli Bahrami 
76469112eddSAli Bahrami 	/* Use initial size first, and double the allocation on each call */
76569112eddSAli Bahrami 	new_n_alloc = (stack->stk_n_alloc == 0) ?
76669112eddSAli Bahrami 	    n_default : (stack->stk_n_alloc * 2);
76769112eddSAli Bahrami 
76869112eddSAli Bahrami 	newaddr = libld_realloc(stack->stk_s, new_n_alloc * elt_size);
76969112eddSAli Bahrami 	if (newaddr == NULL)
77069112eddSAli Bahrami 		return (FALSE);
77169112eddSAli Bahrami 
77269112eddSAli Bahrami 	stack->stk_s = newaddr;
77369112eddSAli Bahrami 	stack->stk_n_alloc = new_n_alloc;
77469112eddSAli Bahrami 	return (TRUE);
77569112eddSAli Bahrami }
77669112eddSAli Bahrami 
77769112eddSAli Bahrami /*
77869112eddSAli Bahrami  * AVL comparison function for cexp_id_node_t items.
77969112eddSAli Bahrami  *
78069112eddSAli Bahrami  * entry:
78169112eddSAli Bahrami  *      n1, n2 - pointers to nodes to be compared
78269112eddSAli Bahrami  *
78369112eddSAli Bahrami  * exit:
78469112eddSAli Bahrami  *      Returns -1 if (n1 < n2), 0 if they are equal, and 1 if (n1 > n2)
78569112eddSAli Bahrami  */
78669112eddSAli Bahrami static int
cexp_ident_cmp(const void * n1,const void * n2)78769112eddSAli Bahrami cexp_ident_cmp(const void *n1, const void *n2)
78869112eddSAli Bahrami {
78969112eddSAli Bahrami 	int	rc;
79069112eddSAli Bahrami 
79169112eddSAli Bahrami 	rc = strcmp(((cexp_id_node_t *)n1)->ceid_name,
79269112eddSAli Bahrami 	    ((cexp_id_node_t *)n2)->ceid_name);
79369112eddSAli Bahrami 
79469112eddSAli Bahrami 	if (rc > 0)
79569112eddSAli Bahrami 		return (1);
79669112eddSAli Bahrami 	if (rc < 0)
79769112eddSAli Bahrami 		return (-1);
79869112eddSAli Bahrami 	return (0);
79969112eddSAli Bahrami }
80069112eddSAli Bahrami 
80169112eddSAli Bahrami 
80269112eddSAli Bahrami /*
80369112eddSAli Bahrami  * Returns True (1) if name is in the conditional expression identifier
80469112eddSAli Bahrami  * AVL tree, and False (0) otherwise.
80569112eddSAli Bahrami  */
80669112eddSAli Bahrami static int
cexp_ident_test(const char * name)80769112eddSAli Bahrami cexp_ident_test(const char *name)
80869112eddSAli Bahrami {
80969112eddSAli Bahrami 	cexp_id_node_t	node;
81069112eddSAli Bahrami 
81169112eddSAli Bahrami 	node.ceid_name = name;
81269112eddSAli Bahrami 	return (avl_find(lms.lms_cexp_id, &node, 0) != NULL);
81369112eddSAli Bahrami }
81469112eddSAli Bahrami 
81569112eddSAli Bahrami /*
81669112eddSAli Bahrami  * Add a new boolean identifier to the conditional expression identifier
81769112eddSAli Bahrami  * AVL tree.
81869112eddSAli Bahrami  *
81969112eddSAli Bahrami  * entry:
82069112eddSAli Bahrami  *	mf - If non-NULL, the mapfile descriptor for the mapfile
82169112eddSAli Bahrami  *		containing the $add directive. NULL if this is an
82269112eddSAli Bahrami  *		initialization call.
82369112eddSAli Bahrami  *	name - Name of identifier. Must point at stable storage that will
82469112eddSAli Bahrami  *		not be moved or modified by the caller following this call.
82569112eddSAli Bahrami  *
82669112eddSAli Bahrami  * exit:
82769112eddSAli Bahrami  *	On success, True (1) is returned and name has been entered.
82869112eddSAli Bahrami  *	On failure, False (0) is returned and an error has been printed.
82969112eddSAli Bahrami  */
83069112eddSAli Bahrami static int
cexp_ident_add(Mapfile * mf,const char * name)83169112eddSAli Bahrami cexp_ident_add(Mapfile *mf, const char *name)
83269112eddSAli Bahrami {
83369112eddSAli Bahrami 	cexp_id_node_t	*node;
83469112eddSAli Bahrami 
83569112eddSAli Bahrami 	if (mf != NULL) {
83669112eddSAli Bahrami 		DBG_CALL(Dbg_map_cexp_id(mf->mf_ofl->ofl_lml, 1,
83769112eddSAli Bahrami 		    mf->mf_name, mf->mf_lineno, name));
83869112eddSAli Bahrami 
83969112eddSAli Bahrami 		/* If is already known, don't do it again */
84069112eddSAli Bahrami 		if (cexp_ident_test(name))
84169112eddSAli Bahrami 			return (1);
84269112eddSAli Bahrami 	}
84369112eddSAli Bahrami 
844*fb12490aSRichard Lowe 	if ((node = libld_calloc(1, sizeof (*node))) == NULL)
84569112eddSAli Bahrami 		return (0);
84669112eddSAli Bahrami 	node->ceid_name = name;
84769112eddSAli Bahrami 	avl_add(lms.lms_cexp_id, node);
84869112eddSAli Bahrami 	return (1);
84969112eddSAli Bahrami }
85069112eddSAli Bahrami 
85169112eddSAli Bahrami /*
85269112eddSAli Bahrami  * Remove a boolean identifier from the conditional expression identifier
85369112eddSAli Bahrami  * AVL tree.
85469112eddSAli Bahrami  *
85569112eddSAli Bahrami  * entry:
85669112eddSAli Bahrami  *	mf - Mapfile descriptor
85769112eddSAli Bahrami  *	name - Name of identifier.
85869112eddSAli Bahrami  *
85969112eddSAli Bahrami  * exit:
86069112eddSAli Bahrami  *	If the name was in the tree, it has been removed. If not,
86169112eddSAli Bahrami  *	then this routine quietly returns.
86269112eddSAli Bahrami  */
86369112eddSAli Bahrami static void
cexp_ident_clear(Mapfile * mf,const char * name)86469112eddSAli Bahrami cexp_ident_clear(Mapfile *mf, const char *name)
86569112eddSAli Bahrami {
86669112eddSAli Bahrami 	cexp_id_node_t	node;
86769112eddSAli Bahrami 	cexp_id_node_t	*real_node;
86869112eddSAli Bahrami 
86969112eddSAli Bahrami 	DBG_CALL(Dbg_map_cexp_id(mf->mf_ofl->ofl_lml, 0,
87069112eddSAli Bahrami 	    mf->mf_name, mf->mf_lineno, name));
87169112eddSAli Bahrami 
87269112eddSAli Bahrami 	node.ceid_name = name;
87369112eddSAli Bahrami 	real_node = avl_find(lms.lms_cexp_id, &node, 0);
87469112eddSAli Bahrami 	if (real_node != NULL)
87569112eddSAli Bahrami 		avl_remove(lms.lms_cexp_id, real_node);
87669112eddSAli Bahrami }
87769112eddSAli Bahrami 
87869112eddSAli Bahrami /*
87969112eddSAli Bahrami  * Initialize the AVL tree that holds the names of the currently defined
88069112eddSAli Bahrami  * boolean identifiers for conditional expressions ($if/$elif).
88169112eddSAli Bahrami  *
88269112eddSAli Bahrami  * entry:
88369112eddSAli Bahrami  *	ofl - Output file descriptor
88469112eddSAli Bahrami  *
88569112eddSAli Bahrami  * exit:
88669112eddSAli Bahrami  *	On success, TRUE (1) is returned and lms.lms_cexp_id is ready for use.
88769112eddSAli Bahrami  *	On failure, FALSE (0) is returned.
88869112eddSAli Bahrami  */
88969112eddSAli Bahrami static Boolean
cexp_ident_init(void)89069112eddSAli Bahrami cexp_ident_init(void)
89169112eddSAli Bahrami {
89269112eddSAli Bahrami 	/* If already done, use it */
89369112eddSAli Bahrami 	if (lms.lms_cexp_id != NULL)
89469112eddSAli Bahrami 		return (TRUE);
89569112eddSAli Bahrami 
896*fb12490aSRichard Lowe 	lms.lms_cexp_id = libld_calloc(1, sizeof (*lms.lms_cexp_id));
89769112eddSAli Bahrami 	if (lms.lms_cexp_id == NULL)
89869112eddSAli Bahrami 		return (FALSE);
89969112eddSAli Bahrami 	avl_create(lms.lms_cexp_id, cexp_ident_cmp, sizeof (cexp_id_node_t),
90069112eddSAli Bahrami 	    SGSOFFSETOF(cexp_id_node_t, ceid_avlnode));
90169112eddSAli Bahrami 
90269112eddSAli Bahrami 
90369112eddSAli Bahrami 	/* ELFCLASS */
90469112eddSAli Bahrami 	if (cexp_ident_add(NULL, (ld_targ.t_m.m_class == ELFCLASS32) ?
90569112eddSAli Bahrami 	    MSG_ORIG(MSG_STR_UELF32) : MSG_ORIG(MSG_STR_UELF64)) == 0)
90669112eddSAli Bahrami 		return (FALSE);
90769112eddSAli Bahrami 
90869112eddSAli Bahrami 	/* Machine */
90969112eddSAli Bahrami 	switch (ld_targ.t_m.m_mach) {
91069112eddSAli Bahrami 	case EM_386:
91169112eddSAli Bahrami 	case EM_AMD64:
91269112eddSAli Bahrami 		if (cexp_ident_add(NULL, MSG_ORIG(MSG_STR_UX86)) == 0)
91369112eddSAli Bahrami 			return (FALSE);
91469112eddSAli Bahrami 		break;
91569112eddSAli Bahrami 
91669112eddSAli Bahrami 	case EM_SPARC:
91769112eddSAli Bahrami 	case EM_SPARCV9:
91869112eddSAli Bahrami 		if (cexp_ident_add(NULL, MSG_ORIG(MSG_STR_USPARC)) == 0)
91969112eddSAli Bahrami 			return (FALSE);
92069112eddSAli Bahrami 		break;
92169112eddSAli Bahrami 	}
92269112eddSAli Bahrami 
92369112eddSAli Bahrami 	/* true is always defined */
92469112eddSAli Bahrami 	if (cexp_ident_add(NULL, MSG_ORIG(MSG_STR_TRUE)) == 0)
92569112eddSAli Bahrami 		return (FALSE);
92669112eddSAli Bahrami 
92769112eddSAli Bahrami 	return (TRUE);
92869112eddSAli Bahrami }
92969112eddSAli Bahrami 
93069112eddSAli Bahrami /*
93169112eddSAli Bahrami  * Validate the string starting at mf->mf_next as being a
93269112eddSAli Bahrami  * boolean conditional expression identifier.
93369112eddSAli Bahrami  *
93469112eddSAli Bahrami  * entry:
93569112eddSAli Bahrami  *	mf - Mapfile descriptor
93669112eddSAli Bahrami  *	len - NULL, or address of variable to receive strlen() of identifier
93769112eddSAli Bahrami  *	directive - If (len == NULL), string giving name of directive being
93869112eddSAli Bahrami  *		processed. Ignored if (len != NULL).
93969112eddSAli Bahrami  *
94069112eddSAli Bahrami  * exit:
94169112eddSAli Bahrami  *	On success:
94269112eddSAli Bahrami  *	-	If len is NULL, a NULL is inserted following the final
94369112eddSAli Bahrami  *		character of the identifier, and the remainder of the string
94469112eddSAli Bahrami  *		is tested to ensure it is empty, or only contains whitespace.
94569112eddSAli Bahrami  *	-	If len is non-NULL, *len is set to the number of characters
94669112eddSAli Bahrami  *		in the identifier, and the rest of the string is not modified.
94769112eddSAli Bahrami  *	-	TRUE (1) is returned
94869112eddSAli Bahrami  *
94969112eddSAli Bahrami  *	On failure, returns FALSE (0).
95069112eddSAli Bahrami  */
95169112eddSAli Bahrami static Boolean
cexp_ident_validate(Mapfile * mf,size_t * len,const char * directive)95269112eddSAli Bahrami cexp_ident_validate(Mapfile *mf, size_t *len, const char *directive)
95369112eddSAli Bahrami {
95469112eddSAli Bahrami 	char	*tail;
95569112eddSAli Bahrami 
95669112eddSAli Bahrami 	if ((tail = ident_delimit(mf)) == NULL)
95769112eddSAli Bahrami 		return (FALSE);
95869112eddSAli Bahrami 
95969112eddSAli Bahrami 	/*
96069112eddSAli Bahrami 	 * If len is non-NULL, we simple count the number of characters
96169112eddSAli Bahrami 	 * consumed by the identifier and are done. If len is NULL, then
96269112eddSAli Bahrami 	 * ensure there's nothing left but whitespace, and NULL terminate
96369112eddSAli Bahrami 	 * the identifier to remove it.
96469112eddSAli Bahrami 	 */
96569112eddSAli Bahrami 	if (len != NULL) {
96669112eddSAli Bahrami 		*len = tail - mf->mf_next;
96769112eddSAli Bahrami 	} else if (*tail != '\0') {
96869112eddSAli Bahrami 		*tail++ = '\0';
96969112eddSAli Bahrami 		while (isspace(*tail))
97069112eddSAli Bahrami 			tail++;
97169112eddSAli Bahrami 		if (*tail != '\0') {
97269112eddSAli Bahrami 			mf_fatal(mf, MSG_INTL(MSG_MAP_BADEXTRA), directive);
97369112eddSAli Bahrami 			return (FALSE);
97469112eddSAli Bahrami 		}
97569112eddSAli Bahrami 	}
97669112eddSAli Bahrami 
97769112eddSAli Bahrami 	return (TRUE);
97869112eddSAli Bahrami }
97969112eddSAli Bahrami 
98069112eddSAli Bahrami /*
98169112eddSAli Bahrami  * Push a new operator onto the conditional expression operator stack.
98269112eddSAli Bahrami  *
98369112eddSAli Bahrami  * entry:
98469112eddSAli Bahrami  *	mf - Mapfile descriptor
98569112eddSAli Bahrami  *	op - Operator to push
98669112eddSAli Bahrami  *
98769112eddSAli Bahrami  * exit:
98869112eddSAli Bahrami  *	On success, TRUE (1) is returned, otherwise FALSE (0).
98969112eddSAli Bahrami  */
99069112eddSAli Bahrami static Boolean
cexp_push_op(cexp_op_t op)99169112eddSAli Bahrami cexp_push_op(cexp_op_t op)
99269112eddSAli Bahrami {
99369112eddSAli Bahrami 	if (STACK_RESERVE(lms.lms_cexp_op_stack, CEXP_OP_STACK_INIT) == 0)
99469112eddSAli Bahrami 		return (FALSE);
99569112eddSAli Bahrami 
99669112eddSAli Bahrami 	STACK_PUSH(lms.lms_cexp_op_stack) = op;
99769112eddSAli Bahrami 	return (TRUE);
99869112eddSAli Bahrami }
99969112eddSAli Bahrami 
100069112eddSAli Bahrami /*
100169112eddSAli Bahrami  * Evaluate the basic operator (non-paren) at the top of lms.lms_cexp_op_stack,
100269112eddSAli Bahrami  * and push the results on lms.lms_cexp_val_stack.
100369112eddSAli Bahrami  *
100469112eddSAli Bahrami  * exit:
100569112eddSAli Bahrami  *	On success, returns TRUE (1). On error, FALSE (0) is returned,
100669112eddSAli Bahrami  *	and the caller is responsible for issuing the error.
100769112eddSAli Bahrami  */
100869112eddSAli Bahrami static Boolean
cexp_eval_op(void)100969112eddSAli Bahrami cexp_eval_op(void)
101069112eddSAli Bahrami {
101169112eddSAli Bahrami 	cexp_op_t	op;
101269112eddSAli Bahrami 	uchar_t		val;
101369112eddSAli Bahrami 
101469112eddSAli Bahrami 	op = STACK_POP(lms.lms_cexp_op_stack);
101569112eddSAli Bahrami 	switch (op) {
101669112eddSAli Bahrami 	case CEXP_OP_AND:
101769112eddSAli Bahrami 		if (lms.lms_cexp_val_stack.stk_n < 2)
101869112eddSAli Bahrami 			return (FALSE);
101969112eddSAli Bahrami 		val = STACK_POP(lms.lms_cexp_val_stack);
102069112eddSAli Bahrami 		STACK_TOP(lms.lms_cexp_val_stack) = val &&
102169112eddSAli Bahrami 		    STACK_TOP(lms.lms_cexp_val_stack);
102269112eddSAli Bahrami 		break;
102369112eddSAli Bahrami 
102469112eddSAli Bahrami 	case CEXP_OP_OR:
102569112eddSAli Bahrami 		if (lms.lms_cexp_val_stack.stk_n < 2)
102669112eddSAli Bahrami 			return (FALSE);
102769112eddSAli Bahrami 		val = STACK_POP(lms.lms_cexp_val_stack);
102869112eddSAli Bahrami 		STACK_TOP(lms.lms_cexp_val_stack) = val ||
102969112eddSAli Bahrami 		    STACK_TOP(lms.lms_cexp_val_stack);
1030