VirtualBox

source: vbox/trunk/src/bldprogs/scmrw.cpp@ 42613

Last change on this file since 42613 was 40534, checked in by vboxsync, 13 years ago

scm: more splitting and some header merging.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.0 KB
Line 
1/* $Id: scmrw.cpp 40534 2012-03-19 11:49:34Z vboxsync $ */
2/** @file
3 * IPRT Testcase / Tool - Source Code Massager.
4 */
5
6/*
7 * Copyright (C) 2010-2012 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/*******************************************************************************
19* Header Files *
20*******************************************************************************/
21#include <iprt/assert.h>
22#include <iprt/ctype.h>
23#include <iprt/dir.h>
24#include <iprt/env.h>
25#include <iprt/file.h>
26#include <iprt/err.h>
27#include <iprt/getopt.h>
28#include <iprt/initterm.h>
29#include <iprt/mem.h>
30#include <iprt/message.h>
31#include <iprt/param.h>
32#include <iprt/path.h>
33#include <iprt/process.h>
34#include <iprt/stream.h>
35#include <iprt/string.h>
36
37#include "scm.h"
38
39
40
41/**
42 * Strip trailing blanks (space & tab).
43 *
44 * @returns True if modified, false if not.
45 * @param pIn The input stream.
46 * @param pOut The output stream.
47 * @param pSettings The settings.
48 */
49bool rewrite_StripTrailingBlanks(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
50{
51 if (!pSettings->fStripTrailingBlanks)
52 return false;
53
54 bool fModified = false;
55 SCMEOL enmEol;
56 size_t cchLine;
57 const char *pchLine;
58 while ((pchLine = ScmStreamGetLine(pIn, &cchLine, &enmEol)) != NULL)
59 {
60 int rc;
61 if ( cchLine == 0
62 || !RT_C_IS_BLANK(pchLine[cchLine - 1]) )
63 rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol);
64 else
65 {
66 cchLine--;
67 while (cchLine > 0 && RT_C_IS_BLANK(pchLine[cchLine - 1]))
68 cchLine--;
69 rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol);
70 fModified = true;
71 }
72 if (RT_FAILURE(rc))
73 return false;
74 }
75 if (fModified)
76 ScmVerbose(pState, 2, " * Stripped trailing blanks\n");
77 return fModified;
78}
79
80/**
81 * Expand tabs.
82 *
83 * @returns True if modified, false if not.
84 * @param pIn The input stream.
85 * @param pOut The output stream.
86 * @param pSettings The settings.
87 */
88bool rewrite_ExpandTabs(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
89{
90 if (!pSettings->fConvertTabs)
91 return false;
92
93 size_t const cchTab = pSettings->cchTab;
94 bool fModified = false;
95 SCMEOL enmEol;
96 size_t cchLine;
97 const char *pchLine;
98 while ((pchLine = ScmStreamGetLine(pIn, &cchLine, &enmEol)) != NULL)
99 {
100 int rc;
101 const char *pchTab = (const char *)memchr(pchLine, '\t', cchLine);
102 if (!pchTab)
103 rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol);
104 else
105 {
106 size_t offTab = 0;
107 const char *pchChunk = pchLine;
108 for (;;)
109 {
110 size_t cchChunk = pchTab - pchChunk;
111 offTab += cchChunk;
112 ScmStreamWrite(pOut, pchChunk, cchChunk);
113
114 size_t cchToTab = cchTab - offTab % cchTab;
115 ScmStreamWrite(pOut, g_szTabSpaces, cchToTab);
116 offTab += cchToTab;
117
118 pchChunk = pchTab + 1;
119 size_t cchLeft = cchLine - (pchChunk - pchLine);
120 pchTab = (const char *)memchr(pchChunk, '\t', cchLeft);
121 if (!pchTab)
122 {
123 rc = ScmStreamPutLine(pOut, pchChunk, cchLeft, enmEol);
124 break;
125 }
126 }
127
128 fModified = true;
129 }
130 if (RT_FAILURE(rc))
131 return false;
132 }
133 if (fModified)
134 ScmVerbose(pState, 2, " * Expanded tabs\n");
135 return fModified;
136}
137
138/**
139 * Worker for rewrite_ForceNativeEol, rewrite_ForceLF and rewrite_ForceCRLF.
140 *
141 * @returns true if modifications were made, false if not.
142 * @param pIn The input stream.
143 * @param pOut The output stream.
144 * @param pSettings The settings.
145 * @param enmDesiredEol The desired end of line indicator type.
146 * @param pszDesiredSvnEol The desired svn:eol-style.
147 */
148static bool rewrite_ForceEol(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings,
149 SCMEOL enmDesiredEol, const char *pszDesiredSvnEol)
150{
151 if (!pSettings->fConvertEol)
152 return false;
153
154 bool fModified = false;
155 SCMEOL enmEol;
156 size_t cchLine;
157 const char *pchLine;
158 while ((pchLine = ScmStreamGetLine(pIn, &cchLine, &enmEol)) != NULL)
159 {
160 if ( enmEol != enmDesiredEol
161 && enmEol != SCMEOL_NONE)
162 {
163 fModified = true;
164 enmEol = enmDesiredEol;
165 }
166 int rc = ScmStreamPutLine(pOut, pchLine, cchLine, enmEol);
167 if (RT_FAILURE(rc))
168 return false;
169 }
170 if (fModified)
171 ScmVerbose(pState, 2, " * Converted EOL markers\n");
172
173 /* Check svn:eol-style if appropriate */
174 if ( pSettings->fSetSvnEol
175 && ScmSvnIsInWorkingCopy(pState))
176 {
177 char *pszEol;
178 int rc = ScmSvnQueryProperty(pState, "svn:eol-style", &pszEol);
179 if ( (RT_SUCCESS(rc) && strcmp(pszEol, pszDesiredSvnEol))
180 || rc == VERR_NOT_FOUND)
181 {
182 if (rc == VERR_NOT_FOUND)
183 ScmVerbose(pState, 2, " * Setting svn:eol-style to %s (missing)\n", pszDesiredSvnEol);
184 else
185 ScmVerbose(pState, 2, " * Setting svn:eol-style to %s (was: %s)\n", pszDesiredSvnEol, pszEol);
186 int rc2 = ScmSvnSetProperty(pState, "svn:eol-style", pszDesiredSvnEol);
187 if (RT_FAILURE(rc2))
188 RTMsgError("ScmSvnSetProperty: %Rrc\n", rc2); /** @todo propagate the error somehow... */
189 }
190 if (RT_SUCCESS(rc))
191 RTStrFree(pszEol);
192 }
193
194 /** @todo also check the subversion svn:eol-style state! */
195 return fModified;
196}
197
198/**
199 * Force native end of line indicator.
200 *
201 * @returns true if modifications were made, false if not.
202 * @param pIn The input stream.
203 * @param pOut The output stream.
204 * @param pSettings The settings.
205 */
206bool rewrite_ForceNativeEol(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
207{
208#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
209 return rewrite_ForceEol(pState, pIn, pOut, pSettings, SCMEOL_CRLF, "native");
210#else
211 return rewrite_ForceEol(pState, pIn, pOut, pSettings, SCMEOL_LF, "native");
212#endif
213}
214
215/**
216 * Force the stream to use LF as the end of line indicator.
217 *
218 * @returns true if modifications were made, false if not.
219 * @param pIn The input stream.
220 * @param pOut The output stream.
221 * @param pSettings The settings.
222 */
223bool rewrite_ForceLF(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
224{
225 return rewrite_ForceEol(pState, pIn, pOut, pSettings, SCMEOL_LF, "LF");
226}
227
228/**
229 * Force the stream to use CRLF as the end of line indicator.
230 *
231 * @returns true if modifications were made, false if not.
232 * @param pIn The input stream.
233 * @param pOut The output stream.
234 * @param pSettings The settings.
235 */
236bool rewrite_ForceCRLF(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
237{
238 return rewrite_ForceEol(pState, pIn, pOut, pSettings, SCMEOL_CRLF, "CRLF");
239}
240
241/**
242 * Strip trailing blank lines and/or make sure there is exactly one blank line
243 * at the end of the file.
244 *
245 * @returns true if modifications were made, false if not.
246 * @param pIn The input stream.
247 * @param pOut The output stream.
248 * @param pSettings The settings.
249 *
250 * @remarks ASSUMES trailing white space has been removed already.
251 */
252bool rewrite_AdjustTrailingLines(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
253{
254 if ( !pSettings->fStripTrailingLines
255 && !pSettings->fForceTrailingLine
256 && !pSettings->fForceFinalEol)
257 return false;
258
259 size_t const cLines = ScmStreamCountLines(pIn);
260
261 /* Empty files remains empty. */
262 if (cLines <= 1)
263 return false;
264
265 /* Figure out if we need to adjust the number of lines or not. */
266 size_t cLinesNew = cLines;
267
268 if ( pSettings->fStripTrailingLines
269 && ScmStreamIsWhiteLine(pIn, cLinesNew - 1))
270 {
271 while ( cLinesNew > 1
272 && ScmStreamIsWhiteLine(pIn, cLinesNew - 2))
273 cLinesNew--;
274 }
275
276 if ( pSettings->fForceTrailingLine
277 && !ScmStreamIsWhiteLine(pIn, cLinesNew - 1))
278 cLinesNew++;
279
280 bool fFixMissingEol = pSettings->fForceFinalEol
281 && ScmStreamGetEolByLine(pIn, cLinesNew - 1) == SCMEOL_NONE;
282
283 if ( !fFixMissingEol
284 && cLines == cLinesNew)
285 return false;
286
287 /* Copy the number of lines we've arrived at. */
288 ScmStreamRewindForReading(pIn);
289
290 size_t cCopied = RT_MIN(cLinesNew, cLines);
291 ScmStreamCopyLines(pOut, pIn, cCopied);
292
293 if (cCopied != cLinesNew)
294 {
295 while (cCopied++ < cLinesNew)
296 ScmStreamPutLine(pOut, "", 0, ScmStreamGetEol(pIn));
297 }
298 /* Fix missing EOL if required. */
299 else if (fFixMissingEol)
300 {
301 if (ScmStreamGetEol(pIn) == SCMEOL_LF)
302 ScmStreamWrite(pOut, "\n", 1);
303 else
304 ScmStreamWrite(pOut, "\r\n", 2);
305 }
306
307 ScmVerbose(pState, 2, " * Adjusted trailing blank lines\n");
308 return true;
309}
310
311/**
312 * Make sure there is no svn:executable keyword on the current file.
313 *
314 * @returns false - the state carries these kinds of changes.
315 * @param pState The rewriter state.
316 * @param pIn The input stream.
317 * @param pOut The output stream.
318 * @param pSettings The settings.
319 */
320bool rewrite_SvnNoExecutable(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
321{
322 if ( !pSettings->fSetSvnExecutable
323 || !ScmSvnIsInWorkingCopy(pState))
324 return false;
325
326 int rc = ScmSvnQueryProperty(pState, "svn:executable", NULL);
327 if (RT_SUCCESS(rc))
328 {
329 ScmVerbose(pState, 2, " * removing svn:executable\n");
330 rc = ScmSvnDelProperty(pState, "svn:executable");
331 if (RT_FAILURE(rc))
332 RTMsgError("ScmSvnSetProperty: %Rrc\n", rc); /** @todo error propagation here.. */
333 }
334 return false;
335}
336
337/**
338 * Make sure the Id and Revision keywords are expanded.
339 *
340 * @returns false - the state carries these kinds of changes.
341 * @param pState The rewriter state.
342 * @param pIn The input stream.
343 * @param pOut The output stream.
344 * @param pSettings The settings.
345 */
346bool rewrite_SvnKeywords(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
347{
348 if ( !pSettings->fSetSvnKeywords
349 || !ScmSvnIsInWorkingCopy(pState))
350 return false;
351
352 char *pszKeywords;
353 int rc = ScmSvnQueryProperty(pState, "svn:keywords", &pszKeywords);
354 if ( RT_SUCCESS(rc)
355 && ( !strstr(pszKeywords, "Id") /** @todo need some function for finding a word in a string. */
356 || !strstr(pszKeywords, "Revision")) )
357 {
358 if (!strstr(pszKeywords, "Id") && !strstr(pszKeywords, "Revision"))
359 rc = RTStrAAppend(&pszKeywords, " Id Revision");
360 else if (!strstr(pszKeywords, "Id"))
361 rc = RTStrAAppend(&pszKeywords, " Id");
362 else
363 rc = RTStrAAppend(&pszKeywords, " Revision");
364 if (RT_SUCCESS(rc))
365 {
366 ScmVerbose(pState, 2, " * changing svn:keywords to '%s'\n", pszKeywords);
367 rc = ScmSvnSetProperty(pState, "svn:keywords", pszKeywords);
368 if (RT_FAILURE(rc))
369 RTMsgError("ScmSvnSetProperty: %Rrc\n", rc); /** @todo error propagation here.. */
370 }
371 else
372 RTMsgError("RTStrAppend: %Rrc\n", rc); /** @todo error propagation here.. */
373 RTStrFree(pszKeywords);
374 }
375 else if (rc == VERR_NOT_FOUND)
376 {
377 ScmVerbose(pState, 2, " * setting svn:keywords to 'Id Revision'\n");
378 rc = ScmSvnSetProperty(pState, "svn:keywords", "Id Revision");
379 if (RT_FAILURE(rc))
380 RTMsgError("ScmSvnSetProperty: %Rrc\n", rc); /** @todo error propagation here.. */
381 }
382 else if (RT_SUCCESS(rc))
383 RTStrFree(pszKeywords);
384
385 return false;
386}
387
388/**
389 * Makefile.kup are empty files, enforce this.
390 *
391 * @returns true if modifications were made, false if not.
392 * @param pIn The input stream.
393 * @param pOut The output stream.
394 * @param pSettings The settings.
395 */
396bool rewrite_Makefile_kup(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
397{
398 /* These files should be zero bytes. */
399 if (pIn->cb == 0)
400 return false;
401 ScmVerbose(pState, 2, " * Truncated file to zero bytes\n");
402 return true;
403}
404
405/**
406 * Rewrite a kBuild makefile.
407 *
408 * @returns true if modifications were made, false if not.
409 * @param pIn The input stream.
410 * @param pOut The output stream.
411 * @param pSettings The settings.
412 *
413 * @todo
414 *
415 * Ideas for Makefile.kmk and Config.kmk:
416 * - sort if1of/ifn1of sets.
417 * - line continuation slashes should only be preceded by one space.
418 */
419bool rewrite_Makefile_kmk(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
420{
421 return false;
422}
423
424/**
425 * Rewrite a C/C++ source or header file.
426 *
427 * @returns true if modifications were made, false if not.
428 * @param pIn The input stream.
429 * @param pOut The output stream.
430 * @param pSettings The settings.
431 *
432 * @todo
433 *
434 * Ideas for C/C++:
435 * - space after if, while, for, switch
436 * - spaces in for (i=0;i<x;i++)
437 * - complex conditional, bird style.
438 * - remove unnecessary parentheses.
439 * - sort defined RT_OS_*|| and RT_ARCH
440 * - sizeof without parenthesis.
441 * - defined without parenthesis.
442 * - trailing spaces.
443 * - parameter indentation.
444 * - space after comma.
445 * - while (x--); -> multi line + comment.
446 * - else statement;
447 * - space between function and left parenthesis.
448 * - TODO, XXX, @todo cleanup.
449 * - Space before/after '*'.
450 * - ensure new line at end of file.
451 * - Indentation of precompiler statements (#ifdef, #defines).
452 * - space between functions.
453 * - string.h -> iprt/string.h, stdarg.h -> iprt/stdarg.h, etc.
454 */
455bool rewrite_C_and_CPP(PSCMRWSTATE pState, PSCMSTREAM pIn, PSCMSTREAM pOut, PCSCMSETTINGSBASE pSettings)
456{
457
458 return false;
459}
460
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