1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2019 Tobias Kortkamp <tobik@FreeBSD.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 #pragma once
29 
30 enum ParserBehavior {
31 	PARSER_DEFAULT = 0,
32 	PARSER_COLLAPSE_ADJACENT_VARIABLES = 1 << 0,
33 	PARSER_DEDUP_TOKENS = 1 << 1,
34 	PARSER_FORMAT_TARGET_COMMANDS = 1 << 2,
35 	PARSER_OUTPUT_DIFF = 1 << 4,
36 	PARSER_OUTPUT_DUMP_TOKENS = 1 << 5,
37 	PARSER_OUTPUT_EDITED = 1 << 6,
38 	PARSER_OUTPUT_INPLACE = 1 << 7,
39 	PARSER_OUTPUT_NO_COLOR = 1 << 8,
40 	PARSER_OUTPUT_RAWLINES = 1 << 9,
41 	PARSER_OUTPUT_REFORMAT = 1 << 10,
42 	PARSER_SANITIZE_APPEND = 1 << 11,
43 	PARSER_UNSORTED_VARIABLES = 1 << 12,
44 	PARSER_ALLOW_FUZZY_MATCHING = 1 << 13,
45 	PARSER_SANITIZE_COMMENTS = 1 << 14,
46 	PARSER_ALWAYS_SORT_VARIABLES = 1 << 15,
47 	PARSER_CHECK_VARIABLE_REFERENCES = 1 << 16,
48 	PARSER_LOAD_LOCAL_INCLUDES = 1 << 17,
49 	PARSER_SANITIZE_CMAKE_ARGS = 1 << 18,
50 };
51 
52 const char *ParserBehavior_tostring(enum ParserBehavior);
53 
54 enum ParserMergeBehavior {
55 	PARSER_MERGE_DEFAULT = 0,
56 	PARSER_MERGE_COMMENTS = 1 << 0,
57 	PARSER_MERGE_OPTIONAL_LIKE_ASSIGN = 1 << 2,
58 	PARSER_MERGE_SHELL_IS_DELETE = 1 << 3,
59 	PARSER_MERGE_AFTER_LAST_IN_GROUP = 1 << 4,
60 	PARSER_MERGE_IGNORE_VARIABLES_IN_CONDITIONALS = 1 << 5,
61 };
62 
63 const char *ParserMergeBehavior_tostring(enum ParserMergeBehavior);
64 
65 enum ParserLookupVariableBehavior {
66 	PARSER_LOOKUP_DEFAULT = 0,
67 	PARSER_LOOKUP_FIRST = 1 << 0,
68 	PARSER_LOOKUP_IGNORE_VARIABLES_IN_CONDITIIONALS = 1 << 1,
69 };
70 
71 const char *ParserLookupVariableBehavior_tostring(enum ParserLookupVariableBehavior);
72 
73 enum ParserError {
74 	PARSER_ERROR_OK,		// human:"no error"
75 	PARSER_ERROR_DIFFERENCES_FOUND, // human:"differences found"
76 	PARSER_ERROR_EDIT_FAILED,	// human:"edit failed"
77 	PARSER_ERROR_EXPECTED_CHAR,	// human:"expected character"
78 	PARSER_ERROR_EXPECTED_INT,	// human:"expected integer"
79 	PARSER_ERROR_EXPECTED_TOKEN,	// human:"expected token"
80 	PARSER_ERROR_INVALID_ARGUMENT,	// human:"invalid argument"
81 	PARSER_ERROR_IO,		// human:"IO error"
82 	PARSER_ERROR_AST_BUILD_FAILED,	// human:"error building AST"
83 	PARSER_ERROR_UNSPECIFIED,	// human:"parse error"
84 };
85 
86 const char *ParserError_human(enum ParserError);
87 const char *ParserError_tostring(enum ParserError);
88 
89 enum ParserMetadata {
90 	PARSER_METADATA_CABAL_EXECUTABLES = 0,
91 	PARSER_METADATA_FLAVORS,
92 	PARSER_METADATA_LICENSES,
93 	PARSER_METADATA_MASTERDIR,
94 	PARSER_METADATA_SHEBANG_LANGS,
95 	PARSER_METADATA_OPTION_DESCRIPTIONS,
96 	PARSER_METADATA_OPTION_GROUPS,
97 	PARSER_METADATA_OPTIONS,
98 	PARSER_METADATA_POST_PLIST_TARGETS,
99 #if PORTFMT_SUBPACKAGES
100 	PARSER_METADATA_SUBPACKAGES,
101 #endif
102 // Used as sentinel, keep PARSER_METADATA_USES last
103 	PARSER_METADATA_USES,
104 };
105 
106 const char *ParserMetadata_tostring(enum ParserMetadata);
107 
108 struct ParserSettings {
109 	const char *filename;
110 	int portsdir;
111 	enum ParserBehavior behavior;
112 	uint32_t target_command_format_threshold;
113 	size_t diff_context;
114 	size_t target_command_format_wrapcol;
115 	size_t variable_wrapcol;
116 	size_t if_wrapcol;
117 	size_t for_wrapcol;
118 	uint32_t debug_level;
119 };
120 
121 struct Array;
122 struct AST;
123 struct Mempool;
124 struct Parser;
125 struct Set;
126 struct Token;
127 
128 typedef void (*ParserEditFn)(struct Parser *, struct AST *, struct Mempool *, void *);
129 
130 #define PARSER_EDIT(name) \
131 	void name(struct Parser *parser, struct AST *root, struct Mempool *extpool, void *userdata)
132 
133 struct Parser *parser_new(struct Mempool *, struct ParserSettings *);
134 void parser_init_settings(struct ParserSettings *);
135 enum ParserError parser_read_from_buffer(struct Parser *, const char *, size_t);
136 enum ParserError parser_read_from_file(struct Parser *, FILE *);
137 enum ParserError parser_read_finish(struct Parser *);
138 struct AST *parser_ast(struct Parser *);
139 char *parser_error_tostring(struct Parser *, struct Mempool *);
140 void parser_set_error(struct Parser *, enum ParserError, const char *);
141 void parser_free(struct Parser *);
142 enum ParserError parser_output_write_to_file(struct Parser *, FILE *);
143 enum ParserError parser_edit(struct Parser *, struct Mempool *, ParserEditFn, void *);
144 void parser_enqueue_output(struct Parser *, const char *);
145 struct AST *parser_lookup_target(struct Parser *, const char *);
146 struct AST *parser_lookup_variable(struct Parser *, const char *, enum ParserLookupVariableBehavior, struct Mempool *, struct Array **, struct Array **);
147 struct AST *parser_lookup_variable_str(struct Parser *, const char *, enum ParserLookupVariableBehavior, struct Mempool *, char **, char **);
148 void *parser_metadata(struct Parser *, enum ParserMetadata);
149 enum ParserError parser_merge(struct Parser *, struct Parser *, enum ParserMergeBehavior);
150 struct ParserSettings parser_settings(struct Parser *);
151