View difference between Paste ID: VsA82fKj and 9MLbD7GC
SHOW: | | - or go back to the newest paste.
1
/**
2
 * Expand environment variables in text (bash style)
3
 * @author gocha <http://twitter.com/gochaism> (I release it into public domain, though)
4
 * FYI: Windows have ExpandEnvironmentStrings function for a similar purpose.
5-
import java.util.Map;
5+
6-
import java.util.regex.Pattern;
6+
7-
import java.util.regex.Matcher;
7+
#include <stdio.h>
8-
import java.util.regex.MatchResult;
8+
#include <stdlib.h>
9
#include <malloc.h>
10-
public class VariablePath
10+
#include <ctype.h>
11
12-
	/**
12+
#ifdef HAVE_STDBOOL_H
13-
	 * Expand environment variables in text
13+
#  include <stdbool.h>
14-
	 * @param path input path string
14+
#else
15-
	 * @param userVariableMap user-defined variable name/value map (null if not needed)
15+
#  ifndef HAVE__BOOL
16-
	 * @param useEnvironmentVariables true if expand environment variables
16+
#    ifdef __cplusplus
17-
	 * @param throwException true if throw Exception if a variable is not defined
17+
       typedef bool _Bool;
18-
	 * @return expanded path string
18+
#    else
19-
	 * @throws IllegalArgumentException if a variable is not defined
19+
#      define _Bool signed char
20-
	 */
20+
#    endif
21-
	private static String expand(String path, Map<String, String> userVariableMap, boolean useEnvironmentVariables, boolean throwException) throws IllegalArgumentException
21+
#  endif
22
#  define bool _Bool
23-
		Pattern variablePattern = Pattern.compile("\\$\\{(.*)\\}|\\$([0-9]+|[A-Za-z_][0-9A-Za-z_]*)");
23+
#  define false 0
24-
		Matcher variableMatcher = variablePattern.matcher(path);
24+
#  define true 1
25-
		StringBuffer pathBuffer = new StringBuffer();
25+
#  define __bool_true_false_are_defined 1
26-
		int lastMatchEnd = 0;
26+
#endif
27-
		while (variableMatcher.find())
27+
28
/**
29-
			// get variable name
29+
 * Expand environment variables in a string (bash style)
30-
			MatchResult matchResult = variableMatcher.toMatchResult();
30+
 * @param str Input path string.
31-
			boolean variableHasPathensis = (matchResult.group(1) != null);
31+
 * @param outputStr Output path string buffer.
32-
			String variableName = (variableHasPathensis ? matchResult.group(1) : matchResult.group(2));
32+
 * @param bufferSize Size of the output buffer in chars. (includes null character)
33-
			String variableContent = null;
33+
 * @return Number of characters written to the buffer (excludes null character). Returns -1 if a fatal error occurred.
34
 */
35-
			// get environment variable
35+
int ExpandEnvironmentVariables(const char *str, char *outputStr, int bufferSize)
36-
			if (useEnvironmentVariables)
36+
37
	int inIndex = 0;
38-
				variableContent = System.getenv(variableName);
38+
	int outIndex = 0;
39
	int varStartIndex = -1;
40-
			// if not available, get user-defined variable
40+
	bool isInVariable = false;
41-
			if (variableContent == null && userVariableMap != null)
41+
	bool hasParenthesis = false;
42
	char *varName = NULL;
43-
				variableContent = userVariableMap.get(variableName);
43+
	char *varValue = NULL;
44
	int varNameLength = 0;
45-
			// if the variable is not defined
45+
	int varValueLength = 0;
46-
			if (variableContent == null)
46+
	unsigned char cIn, cNext;
47
48-
				if (throwException)
48+
	do
49
	{
50-
					// throw Exception if needed
50+
		// check output buffer size
51-
					throw new IllegalArgumentException(path.substring(matchResult.start(), matchResult.end()) + " is not defined.");
51+
		if (outIndex >= bufferSize)
52
		{
53
			outputStr[bufferSize - 1] = '\0';
54
			outIndex = bufferSize + 1;
55-
					// otherwise, use empty string
55+
			break;
56-
					variableContent = "";
56+
57
58
		// read a character
59
		cIn = (unsigned char) str[inIndex];
60-
			// put the value, and a part of string just before the variable
60+
		cNext = (cIn != '\0') ? (unsigned char) str[inIndex + 1] : '\0';
61-
			pathBuffer.append(path.substring(lastMatchEnd, matchResult.start()));
61+
62-
			pathBuffer.append(variableContent);
62+
		if (isInVariable)
63-
			lastMatchEnd = matchResult.end();
63+
64
			// check if we are still in a variable
65-
		// put the rest, and return the result
65+
			if (hasParenthesis)
66-
		pathBuffer.append(path.substring(lastMatchEnd, path.length()));
66+
67-
		return pathBuffer.toString();
67+
				isInVariable = (cIn != '}');
68-
	}
68+
69
				if (cIn == '\0')
70-
	/**
70+
71-
	 * Expand environment variables in text
71+
					fprintf(stderr, "error: missing closing parenthesis.\n");
72-
	 * @param path input path string
72+
					outputStr[outIndex] = '\0';
73-
	 * @return expanded path string
73+
					return -1;
74-
	 */
74+
75-
	public static String expand(String path)
75+
				else if (cIn == '{')
76
				{
77-
		return expand(path, null, true, false);
77+
					fprintf(stderr, "error: bad substitution.\n");
78-
	}
78+
					outputStr[outIndex] = '\0';
79
					return -1;
80-
	/**
80+
81-
	 * VariablePath test method
81+
82-
	 * @param args path string
82+
			else
83-
	 */
83+
84-
	public static void main(String[] args)
84+
				// check for the pattern [0-9]+|[A-Za-z_][0-9A-Za-z_]*
85
				if ((isdigit(str[varStartIndex]) != 0))
86-
		if (args.length > 0)
86+
87
					isInVariable = (isdigit(cIn) != 0);
88-
			try
88+
89
				else
90-
				String path = args[0];
90+
91-
				System.out.println("Input : " + path);
91+
					isInVariable = ((isalnum(cIn) != 0) || cIn == '_');
92-
				System.out.println("Output: " + VariablePath.expand(path));
92+
93
			}
94-
			catch (Exception e)
94+
95
			// reached to end of variable
96-
				e.printStackTrace();
96+
			if (!isInVariable)
97
			{
98
				// get variable name
99
				varNameLength = inIndex - varStartIndex;
100
				varName = (char*) malloc(varNameLength + 1);
101-
			System.out.println("Usage: VariablePath PathString");
101+
				memcpy(varName, &str[varStartIndex], varNameLength);
102
				varName[varNameLength] = '\0';
103-
	}
103+
104
				if (varName[0] != '\0')
105
				{
106
					// expand a variable
107
					varValue = getenv(varName);
108
					if (varValue != NULL)
109
					{
110
						varValueLength = strlen(varValue);
111
						if (outIndex + varValueLength <= bufferSize)
112
						{
113
							memcpy(&outputStr[outIndex], varValue, varValueLength);
114
							outIndex += varValueLength;
115
						}
116
						else
117
						{
118
							memcpy(&outputStr[outIndex], varValue, bufferSize - outIndex);
119
							outIndex = bufferSize;
120
						}
121
122
						if (outIndex == bufferSize)
123
						{
124
							outputStr[bufferSize - 1] = '\0';
125
							outIndex = bufferSize + 1;
126
							break;
127
						}
128
					}
129
					else
130
					{
131
						fprintf(stderr, "error: ${%s} is not defined.\n", varName);
132
						outputStr[outIndex] = '\0';
133
						return -1;
134
					}
135
136
					if (!hasParenthesis)
137
					{
138
						// redo the same character
139
						inIndex--;
140
						continue;
141
					}
142
				}
143
				else
144
				{
145
					// not a variable
146
					if (hasParenthesis)
147
					{
148
						fprintf(stderr, "error: variable name must not be empty.\n");
149
						outputStr[outIndex] = '\0';
150
						return -1;
151
					}
152
					else
153
					{
154
						outputStr[outIndex] = '$';
155
						outIndex++;
156
157
						if (outIndex < bufferSize)
158
						{
159
							outputStr[outIndex] = cIn;
160
							outIndex++;
161
						}
162
					}
163
				}
164
			}
165
		}
166
		else
167
		{
168
			if (cIn == '$')
169
			{
170
				// start of a variable
171
				isInVariable = true;
172
173
				// check if it has a parenthesis
174
				if (cNext == '{')
175
				{
176
					hasParenthesis = true;
177
					inIndex++;
178
				}
179
				else
180
				{
181
					hasParenthesis = false;
182
				}
183
				varStartIndex = inIndex + 1;
184
			}
185
			else
186
			{
187
				// plain string
188
				outputStr[outIndex] = cIn;
189
				outIndex++;
190
			}
191
		}
192
193
#ifdef MS932_SUPPORT
194
		// check for the lead-byte of MS932 (Windows-31J)
195
		if ((cIn >= 0x81 && cIn <= 0x9f) || (cIn >= 0xe0 && cIn <= 0xfc))
196
		{
197
			// check for the trailer-byte as well
198
			if ((cNext >= 0x40 && cNext <= 0x7e) || (cNext >= 0x80 && cNext <= 0xfc))
199
			{
200
				if (!isInVariable)
201
				{
202
					if (outIndex + 1 < bufferSize)
203
					{
204
						outputStr[outIndex] = cNext;
205
					}
206
					else
207
					{
208
						outputStr[outIndex - 1] = '\0';
209
					}
210
					outIndex++;
211
				}
212
				inIndex++;
213
			}
214
		}
215
#endif
216
	} while (str[inIndex++] != '\0');
217
	return outIndex - 1;
218
}
219
220
// test routine
221
int main(int argc, char *argv[])
222
{
223
	char s[4096];
224
	char *pat;
225
	int ret;
226
227
	pat = "HOME";
228
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
229
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
230
231
	pat = "$HOME";
232
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
233
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
234
235
	pat = "${HOME}";
236
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
237
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
238
239
	pat = "${HOME!}";
240
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
241
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
242
243
	pat = "$HOME!";
244
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
245
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
246
247
	pat = "$HOME$HOME";
248
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
249
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
250
251
	pat = "$123ABC";
252
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
253
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
254
255
	pat = "";
256
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
257
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
258
259
	pat = "$";
260
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
261
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
262
263
	pat = "${";
264
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
265
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
266
267
	pat = "${{";
268
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
269
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
270
271
	pat = "$}";
272
	ret = ExpandEnvironmentVariables(pat, s, sizeof(s));
273
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
274
275
	pat = "$NOT_DEFINED";
276
	ret = ExpandEnvironmentVariables(pat, s, 8);
277
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
278
279
	pat = "ABCDEFG$HOME";
280
	ret = ExpandEnvironmentVariables(pat, s, 8);
281
	printf("\"%s\" -> \"%s\" (%d)\n\n", pat, s, ret);
282
283
	return 0;
284
}