1 /*
2  * Copyright (c) 2016,2017,2019 Daichi GOTO
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #define VERSION "20190812"
29 #define CMDNAME "gyo_select"
30 #define ALIAS "gyosel row_select"
31 
32 #include <limits.h>
33 #ifdef __linux__
34 #include <db_185.h>
35 #else
36 #include <db.h>
37 #endif
38 
39 #include "ttt.h"
40 
41 void simple_comparison(int, char**);
42 
43 #define TGT_RETU_PROCESS(BUF,BUFLEN,INDEX) \
44 	fp_no_output = 1; \
45 	b_key.data = BUF; \
46 	b_key.size = strlen(b_key.data) + 1; \
47 	b_val.data = "1"; \
48 	b_val.size = 2; \
49 	trees[i]->put(trees[i], &b_key, &b_val, 0);
50 
51 #define NOTGT_RETU_PROCESS(BUF,BUFLEN,INDEX) \
52 	fp_no_output = 1; \
53 
54 #define END_OF_LINE_RETU_PROCESS
55 
56 #define TGT_GYO_PROCESS(GYO_BUFFER,NF) \
57 	nf = NF; \
58 	if (FLAG_1 && first_line) { \
59 		first_line = 0; \
60 		goto gyo_not_match; \
61 	} \
62 	if (!FLAG_o) { \
63 		/* AND CONDITION */ \
64 		for (int i = 1; i <= match_count; i++) { \
65 			if (NF < R_ARGV[i]) \
66 				goto gyo_not_match; \
67 			if ('!' != R_ARGV_DELIM[i] && \
68 			    '@' == GYO_BUFFER[R_ARGV[i]][0] && \
69 			   '\0' == GYO_BUFFER[R_ARGV[i]][1] && \
70 			   !('@' == R_ARGV_ARG1[i][0] && \
71 			    '\0' == R_ARGV_ARG1[i][1])) \
72 				goto gyo_not_match; \
73 			if (NULL != trees[i]) { \
74 				b_key.data = GYO_BUFFER[R_ARGV[i]]; \
75 				b_key.size = strlen(b_key.data) + 1; \
76 				if (1 == trees[i]->get(trees[i], \
77 					&b_key, &b_val, 0)) \
78 					goto gyo_not_match; \
79 			} \
80 			else { \
81 				if (FLAG_N) { \
82 					errno = 0; \
83 					n1 = strtoll(GYO_BUFFER[R_ARGV[i]],\
84 						(char **)NULL, 10); \
85 					if (EINVAL == errno) \
86 						goto gyo_not_match; \
87 					cmpret = 0; \
88 					if (n1 > n2[i]) \
89 						cmpret = 1; \
90 					else if (n1 < n2[i]) \
91 						cmpret = -1; \
92 				} \
93 				else \
94 					cmpret = \
95 					strcmp(GYO_BUFFER[R_ARGV[i]], \
96 						R_ARGV_ARG1[i]); \
97 				switch (R_ARGV_DELIM[i]) { \
98 				case '>': \
99 					if (0 >= cmpret) \
100 						goto gyo_not_match; \
101 					break; \
102 				case '<': \
103 					if (0 <= cmpret) \
104 						goto gyo_not_match; \
105 					break; \
106 				case '!': \
107 					if (0 == cmpret) \
108 						goto gyo_not_match; \
109 					break; \
110 				default: \
111 					if (0 != cmpret) \
112 						goto gyo_not_match; \
113 					break; \
114 				} \
115 			} \
116 		} \
117 		goto gyo_match; \
118 	} \
119 	else { \
120 		/* OR CONDITION */ \
121 		for (int i = 1; i <= match_count; i++) { \
122 			if (NF < R_ARGV[i]) \
123 				goto gyo_not_match; \
124 			if ('!' != R_ARGV_DELIM[i] && \
125 			    '@' == GYO_BUFFER[R_ARGV[i]][0] && \
126 			   '\0' == GYO_BUFFER[R_ARGV[i]][1] && \
127 			   !('@' == R_ARGV_ARG1[i][0] && \
128 			    '\0' == R_ARGV_ARG1[i][1])) \
129 				continue; \
130 			if (NULL != trees[i]) { \
131 				b_key.data = GYO_BUFFER[R_ARGV[i]]; \
132 				b_key.size = strlen(b_key.data) + 1; \
133 				if (0 == trees[i]->get(trees[i], \
134 					&b_key, &b_val, 0)) \
135 					goto gyo_match; \
136 			} \
137 			else { \
138 				if (FLAG_N) { \
139 					errno = 0; \
140 					n1 = strtoll(GYO_BUFFER[R_ARGV[i]],\
141 						(char **)NULL, 10); \
142 					if (EINVAL == errno) \
143 						continue; \
144 					cmpret = 0; \
145 					if (n1 > n2[i]) \
146 						cmpret = 1; \
147 					else if (n1 < n2[i]) \
148 						cmpret = -1; \
149 				} \
150 				else \
151 					cmpret = \
152 					strcmp(GYO_BUFFER[R_ARGV[i]], \
153 						R_ARGV_ARG1[i]); \
154 				switch (R_ARGV_DELIM[i]) { \
155 				case '>': \
156 					if (0 < cmpret) \
157 						goto gyo_match; \
158 					break; \
159 				case '<': \
160 					if (0 > cmpret) \
161 						goto gyo_match; \
162 					break; \
163 				case '!': \
164 					if (0 != cmpret) \
165 						goto gyo_match; \
166 					break; \
167 				default: \
168 					if (0 == cmpret) \
169 						goto gyo_match; \
170 					break; \
171 				} \
172 			} \
173 		} \
174 		goto gyo_not_match; \
175 	} \
176 gyo_match: \
177 	match_or_not = 0; \
178 	if (!FLAG_n) { \
179 		if (R_ARGC == match_count) { \
180 			for (int i = 1; i < NF; i++) \
181 				PRINT(GYO_BUFFER[i], " "); \
182 			PRINT(GYO_BUFFER[NF], "\n"); \
183 		} \
184 		else { \
185 	                for (int i = match_count+1; i < R_ARGC; i++) \
186 	                        if (R_ARGV[i] > NF || \
187 	                                NULL == GYO_BUFFER[R_ARGV[i]]) { \
188 					PRINT("@", " "); \
189 				} \
190 	                        else { \
191 					PRINT(GYO_BUFFER[R_ARGV[i]], " "); \
192 				} \
193 	                if (R_ARGV[R_ARGC] > NF || \
194 	                        NULL == GYO_BUFFER[R_ARGV[R_ARGC]]) { \
195 				PRINT("@", "\n"); \
196 			} \
197 	                else \
198 				PRINT(GYO_BUFFER[R_ARGV[R_ARGC]], "\n"); \
199 		} \
200 	} \
201 gyo_not_match:
202 
203 #define PRINT(TARGET,DELIMITER) \
204 	if ('@' == TARGET[0] && '\0' == TARGET[1]) { \
205 		printf("%s%s", val, DELIMITER); \
206 	} \
207 	else \
208 		printf("%s%s", TARGET, DELIMITER);
209