VirtualBox

source: kBuild/trunk/src/kmk/kmkbuiltin/append.c@ 3154

Last change on this file since 3154 was 3141, checked in by bird, 7 years ago

kmk: linux merge fixes.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 9.0 KB
Line 
1/* $Id: append.c 3141 2018-03-14 21:58:32Z bird $ */
2/** @file
3 * kMk Builtin command - append text to file.
4 */
5
6/*
7 * Copyright (c) 2005-2010 knut st. osmundsen <[email protected]>
8 *
9 * This file is part of kBuild.
10 *
11 * kBuild is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * kBuild is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with kBuild. If not, see <http://www.gnu.org/licenses/>
23 *
24 */
25
26/*******************************************************************************
27* Header Files *
28*******************************************************************************/
29#ifndef kmk_builtin_append
30# include "makeint.h"
31# include "filedef.h"
32# include "variable.h"
33#else
34# include "config.h"
35#endif
36#include <string.h>
37#include <stdio.h>
38#ifdef HAVE_ALLOCA_H
39# include <alloca.h>
40#endif
41#include "err.h"
42#include "kmkbuiltin.h"
43
44
45/**
46 * Prints the usage and return 1.
47 */
48static int usage(FILE *pf)
49{
50 fprintf(pf,
51 "usage: %s [-dcnNtv] file [string ...]\n"
52 " or: %s --version\n"
53 " or: %s --help\n"
54 "\n"
55 "Options:\n"
56 " -d Enclose the output in define ... endef, taking the name from\n"
57 " the first argument following the file name.\n"
58 " -c Output the command for specified target(s). [builtin only]\n"
59 " -i look for --insert-command=trg and --insert-variable=var. [builtin only]\n"
60 " -n Insert a newline between the strings.\n"
61 " -N Suppress the trailing newline.\n"
62 " -t Truncate the file instead of appending\n"
63 " -v Output the value(s) for specified variable(s). [builtin only]\n"
64 ,
65 g_progname, g_progname, g_progname);
66 return 1;
67}
68
69
70/**
71 * Appends text to a textfile, creating the textfile if necessary.
72 */
73int kmk_builtin_append(int argc, char **argv, char **envp)
74{
75 int i;
76 int fFirst;
77 int iFile;
78 FILE *pFile;
79 int fNewline = 0;
80 int fNoTrailingNewline = 0;
81 int fTruncate = 0;
82 int fDefine = 0;
83 int fVariables = 0;
84 int fCommands = 0;
85#ifndef kmk_builtin_append
86 int fLookForInserts = 0;
87#endif
88
89 g_progname = argv[0];
90
91 /*
92 * Parse options.
93 */
94 i = 1;
95 while (i < argc
96 && argv[i][0] == '-'
97 && argv[i][1] != '\0' /* '-' is a file */
98 && strchr("-cdinNtv", argv[i][1]) /* valid option char */
99 )
100 {
101 char *psz = &argv[i][1];
102 if (*psz != '-')
103 {
104 do
105 {
106 switch (*psz)
107 {
108 case 'c':
109 if (fVariables)
110 {
111 errx(1, "Option '-c' clashes with '-v'.");
112 return usage(stderr);
113 }
114#ifndef kmk_builtin_append
115 fCommands = 1;
116 break;
117#else
118 errx(1, "Option '-c' isn't supported in external mode.");
119 return usage(stderr);
120#endif
121 case 'd':
122 if (fVariables)
123 {
124 errx(1, "Option '-d' must come before '-v'!");
125 return usage(stderr);
126 }
127 fDefine = 1;
128 break;
129 case 'i':
130 if (fVariables || fCommands)
131 {
132 errx(1, fVariables ? "Option '-i' clashes with '-v'." : "Option '-i' clashes with '-c'.");
133 return usage(stderr);
134 }
135#ifndef kmk_builtin_append
136 fLookForInserts = 1;
137 break;
138#else
139 errx(1, "Option '-C' isn't supported in external mode.");
140 return usage(stderr);
141#endif
142 case 'n':
143 fNewline = 1;
144 break;
145 case 'N':
146 fNoTrailingNewline = 1;
147 break;
148 case 't':
149 fTruncate = 1;
150 break;
151 case 'v':
152 if (fCommands)
153 {
154 errx(1, "Option '-v' clashes with '-c'.");
155 return usage(stderr);
156 }
157#ifndef kmk_builtin_append
158 fVariables = 1;
159 break;
160#else
161 errx(1, "Option '-v' isn't supported in external mode.");
162 return usage(stderr);
163#endif
164 default:
165 errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]);
166 return usage(stderr);
167 }
168 } while (*++psz);
169 }
170 else if (!strcmp(psz, "-help"))
171 {
172 usage(stdout);
173 return 0;
174 }
175 else if (!strcmp(psz, "-version"))
176 return kbuild_version(argv[0]);
177 else
178 break;
179 i++;
180 }
181
182 if (i + fDefine >= argc)
183 {
184 if (i <= argc)
185 errx(1, "missing filename!");
186 else
187 errx(1, "missing define name!");
188 return usage(stderr);
189 }
190
191 /*
192 * Open the output file.
193 */
194 iFile = i;
195 pFile = fopen(argv[i], fTruncate ? "w" : "a");
196 if (!pFile)
197 return err(1, "failed to open '%s'", argv[i]);
198
199 /*
200 * Start define?
201 */
202 if (fDefine)
203 {
204 i++;
205 fprintf(pFile, "define %s\n", argv[i]);
206 }
207
208 /*
209 * Append the argument strings to the file
210 */
211 fFirst = 1;
212 for (i++; i < argc; i++)
213 {
214 const char *psz = argv[i];
215 size_t cch = strlen(psz);
216 if (!fFirst)
217 fputc(fNewline ? '\n' : ' ', pFile);
218#ifndef kmk_builtin_append
219 if (fCommands)
220 {
221 char *pszOldBuf;
222 unsigned cchOldBuf;
223 char *pchEnd;
224
225 install_variable_buffer(&pszOldBuf, &cchOldBuf);
226
227 pchEnd = func_commands(variable_buffer, &argv[i], "commands");
228 fwrite(variable_buffer, 1, pchEnd - variable_buffer, pFile);
229
230 restore_variable_buffer(pszOldBuf, cchOldBuf);
231 }
232 else if (fVariables)
233 {
234 struct variable *pVar = lookup_variable(psz, cch);
235 if (!pVar)
236 continue;
237 if ( !pVar->recursive
238 || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar))
239 fwrite(pVar->value, 1, pVar->value_length, pFile);
240 else
241 {
242 char *pszExpanded = allocated_variable_expand(pVar->value);
243 fwrite(pszExpanded, 1, strlen(pszExpanded), pFile);
244 free(pszExpanded);
245 }
246 }
247 else if (fLookForInserts && strncmp(psz, "--insert-command=", 17) == 0)
248 {
249 char *pszOldBuf;
250 unsigned cchOldBuf;
251 char *pchEnd;
252
253 install_variable_buffer(&pszOldBuf, &cchOldBuf);
254
255 psz += 17;
256 pchEnd = func_commands(variable_buffer, (char **)&psz, "commands");
257 fwrite(variable_buffer, 1, pchEnd - variable_buffer, pFile);
258
259 restore_variable_buffer(pszOldBuf, cchOldBuf);
260 }
261 else if (fLookForInserts && strncmp(psz, "--insert-variable=", 18) == 0)
262 {
263 struct variable *pVar = lookup_variable(psz + 18, cch);
264 if (!pVar)
265 continue;
266 if ( !pVar->recursive
267 || IS_VARIABLE_RECURSIVE_WITHOUT_DOLLAR(pVar))
268 fwrite(pVar->value, 1, pVar->value_length, pFile);
269 else
270 {
271 char *pszExpanded = allocated_variable_expand(pVar->value);
272 fwrite(pszExpanded, 1, strlen(pszExpanded), pFile);
273 free(pszExpanded);
274 }
275 }
276 else
277#endif
278 fwrite(psz, 1, cch, pFile);
279 fFirst = 0;
280 }
281
282 /*
283 * End the define?
284 */
285 if (fDefine)
286 {
287 if (fFirst)
288 fwrite("\nendef", 1, sizeof("\nendef") - 1, pFile);
289 else
290 fwrite("endef", 1, sizeof("endef") - 1, pFile);
291 }
292
293 /*
294 * Add the final newline (unless supressed) and close the file.
295 */
296 if ( ( !fNoTrailingNewline
297 && fputc('\n', pFile) == EOF)
298 || ferror(pFile))
299 {
300 fclose(pFile);
301 return errx(1, "error writing to '%s'!", argv[iFile]);
302 }
303 if (fclose(pFile))
304 return err(1, "failed to fclose '%s'!", argv[iFile]);
305 return 0;
306}
307
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette