VirtualBox

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

Last change on this file since 2134 was 2121, checked in by bird, 16 years ago

kmk: make sure alloca.h gets included (Solaris again).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.2 KB
Line 
1/* $Id: append.c 2121 2008-12-25 14:07:56Z bird $ */
2/** @file
3 * kMk Builtin command - append text to file.
4 */
5
6/*
7 * Copyright (c) 2005-2008 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 "make.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 " -n Insert a newline between the strings.\n"
60 " -N Suppress the trailing newline.\n"
61 " -t Truncate the file instead of appending\n"
62 " -v Output the value(s) for specified variable(s). [builtin only]\n"
63 ,
64 g_progname, g_progname, g_progname);
65 return 1;
66}
67
68
69/**
70 * Appends text to a textfile, creating the textfile if necessary.
71 */
72int kmk_builtin_append(int argc, char **argv, char **envp)
73{
74 int i;
75 int fFirst;
76 int iFile;
77 FILE *pFile;
78 int fNewline = 0;
79 int fNoTrailingNewline = 0;
80 int fTruncate = 0;
81 int fDefine = 0;
82 int fVariables = 0;
83 int fCommands = 0;
84
85 g_progname = argv[0];
86
87 /*
88 * Parse options.
89 */
90 i = 1;
91 while (i < argc
92 && argv[i][0] == '-'
93 && argv[i][1] != '\0' /* '-' is a file */
94 && strchr("-cdnNtv", argv[i][1]) /* valid option char */
95 )
96 {
97 char *psz = &argv[i][1];
98 if (*psz != '-')
99 {
100 do
101 {
102 switch (*psz)
103 {
104 case 'c':
105 if (fVariables)
106 {
107 errx(1, "Option '-c' clashes with '-v'.");
108 return usage(stderr);
109 }
110#ifndef kmk_builtin_append
111 fCommands = 1;
112 break;
113#else
114 errx(1, "Option '-c' isn't supported in external mode.");
115 return usage(stderr);
116#endif
117 case 'd':
118 if (fVariables)
119 {
120 errx(1, "Option '-d' must come before '-v'!");
121 return usage(stderr);
122 }
123 fDefine = 1;
124 break;
125 case 'n':
126 fNewline = 1;
127 break;
128 case 'N':
129 fNoTrailingNewline = 1;
130 break;
131 case 't':
132 fTruncate = 1;
133 break;
134 case 'v':
135 if (fCommands)
136 {
137 errx(1, "Option '-v' clashes with '-c'.");
138 return usage(stderr);
139 }
140#ifndef kmk_builtin_append
141 fVariables = 1;
142 break;
143#else
144 errx(1, "Option '-v' isn't supported in external mode.");
145 return usage(stderr);
146#endif
147 default:
148 errx(1, "Invalid option '%c'! (%s)", *psz, argv[i]);
149 return usage(stderr);
150 }
151 } while (*++psz);
152 }
153 else if (!strcmp(psz, "-help"))
154 {
155 usage(stdout);
156 return 0;
157 }
158 else if (!strcmp(psz, "-version"))
159 return kbuild_version(argv[0]);
160 else
161 break;
162 i++;
163 }
164
165 if (i + fDefine >= argc)
166 {
167 if (i <= argc)
168 errx(1, "missing filename!");
169 else
170 errx(1, "missing define name!");
171 return usage(stderr);
172 }
173
174 /*
175 * Open the output file.
176 */
177 iFile = i;
178 pFile = fopen(argv[i], fTruncate ? "w" : "a");
179 if (!pFile)
180 return err(1, "failed to open '%s'.", argv[i]);
181
182 /*
183 * Start define?
184 */
185 if (fDefine)
186 {
187 i++;
188 fprintf(pFile, "define %s\n", argv[i]);
189 }
190
191 /*
192 * Append the argument strings to the file
193 */
194 fFirst = 1;
195 for (i++; i < argc; i++)
196 {
197 const char *psz = argv[i];
198 size_t cch = strlen(psz);
199 if (!fFirst)
200 fputc(fNewline ? '\n' : ' ', pFile);
201#ifndef kmk_builtin_append
202 if (fCommands)
203 {
204 char *pszOldBuf;
205 unsigned cchOldBuf;
206 char *pchEnd;
207
208 install_variable_buffer(&pszOldBuf, &cchOldBuf);
209
210 pchEnd = func_commands(variable_buffer, &argv[i], "commands");
211 fwrite(variable_buffer, 1, pchEnd - variable_buffer, pFile);
212
213 restore_variable_buffer(pszOldBuf, cchOldBuf);
214 }
215 else if (fVariables)
216 {
217 struct variable *pVar = lookup_variable(psz, cch);
218 if (!pVar)
219 continue;
220 if ( pVar->recursive
221 && memchr(pVar->value, '$', pVar->value_length))
222 {
223 char *pszExpanded = allocated_variable_expand(pVar->value);
224 fwrite(pszExpanded, 1, strlen(pszExpanded), pFile);
225 free(pszExpanded);
226 }
227 else
228 fwrite(pVar->value, 1, pVar->value_length, pFile);
229 }
230 else
231#endif
232 fwrite(psz, 1, cch, pFile);
233 fFirst = 0;
234 }
235
236 /*
237 * End the define?
238 */
239 if (fDefine)
240 {
241 if (fFirst)
242 fwrite("\nendef", 1, sizeof("\nendef") - 1, pFile);
243 else
244 fwrite("endef", 1, sizeof("endef") - 1, pFile);
245 }
246
247 /*
248 * Add the final newline (unless supressed) and close the file.
249 */
250 if ( ( !fNoTrailingNewline
251 && fputc('\n', pFile) == EOF)
252 || ferror(pFile))
253 {
254 fclose(pFile);
255 return errx(1, "error writing to '%s'!", argv[iFile]);
256 }
257 if (fclose(pFile))
258 return err(1, "failed to fclose '%s'!", argv[iFile]);
259 return 0;
260}
261
Note: See TracBrowser for help on using the repository browser.

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