VirtualBox

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

Last change on this file since 2060 was 2019, checked in by bird, 16 years ago

GPLv2 -> GPLv3. See Ticket #44 for clarifications. Fixes #44.

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