VirtualBox

source: vbox/trunk/src/bldprogs/VBoxCompilerPlugInsCommon.cpp@ 56977

Last change on this file since 56977 was 56977, checked in by vboxsync, 9 years ago

gccplugin: restructured the code a little, should be able to detect missing arguments now.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1/* $Id: VBoxCompilerPlugInsCommon.cpp 56977 2015-07-18 17:43:19Z vboxsync $ */
2/** @file
3 * VBoxCompilerPlugInsCommon - Code common to the compiler plug-ins.
4 */
5
6/*
7 * Copyright (C) 2006-2015 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/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define VBOX_COMPILER_PLUG_IN_AGNOSTIC
23#include "VBoxCompilerPlugIns.h"
24
25#include <iprt/string.h>
26
27
28/*********************************************************************************************************************************
29* Defined Constants And Macros *
30*********************************************************************************************************************************/
31#define MY_ISDIGIT(c) ((c) >= '0' && (c) <= '9')
32
33
34
35/**
36 * Does the actual format string checking.
37 *
38 * @todo Move this to different file common to both GCC and CLANG later.
39 *
40 * @param pState The format string checking state.
41 * @param pszFmt The format string.
42 */
43void MyCheckFormatCString(PVFMTCHKSTATE pState, const char *pszFmt)
44{
45 dprintf("checker2: \"%s\" at %s:%d col %d\n", pszFmt,
46 MYSTATE_FMT_FILE(pState), MYSTATE_FMT_LINE(pState), MYSTATE_FMT_COLUMN(pState));
47 pState->pszFmt = pszFmt;
48
49 unsigned iArg = 0;
50 for (;;)
51 {
52 /*
53 * Skip to the next argument.
54 * Quits the loop with the first char following the '%' in 'ch'.
55 */
56 char ch;
57 for (;;)
58 {
59 ch = *pszFmt++;
60 if (ch == '%')
61 {
62 ch = *pszFmt++;
63 if (ch != '%')
64 break;
65 }
66 else if (ch == '\0')
67 {
68 VFmtChkVerifyEndOfArgs(pState, iArg);
69 return;
70 }
71 }
72 const char * const pszPct = pszFmt - 2;
73
74 /*
75 * Flags
76 */
77 uint32_t fFlags = 0;
78 for (;;)
79 {
80 uint32_t fFlag;
81 switch (ch)
82 {
83 case '#': fFlag = RTSTR_F_SPECIAL; break;
84 case '-': fFlag = RTSTR_F_LEFT; break;
85 case '+': fFlag = RTSTR_F_PLUS; break;
86 case ' ': fFlag = RTSTR_F_BLANK; break;
87 case '0': fFlag = RTSTR_F_ZEROPAD; break;
88 case '\'': fFlag = RTSTR_F_THOUSAND_SEP; break;
89 default: fFlag = 0; break;
90 }
91 if (!fFlag)
92 break;
93 if (fFlags & fFlag)
94 VFmtChkWarnFmt(pState, pszPct, "duplicate flag '%c'", ch);
95 fFlags |= fFlag;
96 ch = *pszFmt++;
97 }
98
99 /*
100 * Width.
101 */
102 int cchWidth = -1;
103 if (MY_ISDIGIT(ch))
104 {
105 cchWidth = ch - '0';
106 while ( (ch = *pszFmt++) != '\0'
107 && MY_ISDIGIT(ch))
108 {
109 cchWidth *= 10;
110 cchWidth += ch - '0';
111 }
112 fFlags |= RTSTR_F_WIDTH;
113 }
114 else if (ch == '*')
115 {
116 VFmtChkRequireIntArg(pState, pszPct, iArg, "width should be an 'int' sized argument");
117 iArg++;
118 cchWidth = 0;
119 fFlags |= RTSTR_F_WIDTH;
120 }
121
122 /*
123 * Precision
124 */
125 int cchPrecision = -1;
126 if (ch == '.')
127 {
128 ch = *pszFmt++;
129 if (MY_ISDIGIT(ch))
130 {
131 cchPrecision = ch - '0';
132 while ( (ch = *pszFmt++) != '\0'
133 && MY_ISDIGIT(ch))
134 {
135 cchPrecision *= 10;
136 cchPrecision += ch - '0';
137 }
138 }
139 else if (ch == '*')
140 {
141 VFmtChkRequireIntArg(pState, pszPct, iArg, "precision should be an 'int' sized argument");
142 iArg++;
143 cchWidth = 0;
144 }
145 else
146 VFmtChkWarnFmt(pState, pszPct, "Missing precision value, only got the '.'");
147 if (cchPrecision < 0)
148 {
149 VFmtChkWarnFmt(pState, pszPct, "Negative precision value: %d", cchPrecision);
150 cchPrecision = 0;
151 }
152 fFlags |= RTSTR_F_PRECISION;
153 }
154
155 /*
156 * Argument size.
157 */
158 char chSize = ch;
159 switch (ch)
160 {
161 default:
162 chSize = '\0';
163 break;
164
165 case 'z':
166 case 'L':
167 case 'j':
168 case 't':
169 ch = *pszFmt++;
170 break;
171
172 case 'l':
173 ch = *pszFmt++;
174 if (ch == 'l')
175 {
176 chSize = 'L';
177 ch = *pszFmt++;
178 }
179 break;
180
181 case 'h':
182 ch = *pszFmt++;
183 if (ch == 'h')
184 {
185 chSize = 'H';
186 ch = *pszFmt++;
187 }
188 break;
189
190 case 'I': /* Used by Win32/64 compilers. */
191 if ( pszFmt[0] == '6'
192 && pszFmt[1] == '4')
193 {
194 pszFmt += 2;
195 chSize = 'L';
196 }
197 else if ( pszFmt[0] == '3'
198 && pszFmt[1] == '2')
199 {
200 pszFmt += 2;
201 chSize = 0;
202 }
203 else
204 chSize = 'j';
205 ch = *pszFmt++;
206 break;
207
208 case 'q': /* Used on BSD platforms. */
209 chSize = 'L';
210 ch = *pszFmt++;
211 break;
212 }
213
214 /*
215 * The type.
216 */
217 switch (ch)
218 {
219 /*
220 * Nested extensions.
221 */
222 case 'M': /* replace the format string (not stacked yet). */
223 {
224 if (*pszFmt)
225 VFmtChkWarnFmt(pState, pszFmt, "Characters following '%%M' will be ignored");
226 if (chSize != '\0')
227 VFmtChkWarnFmt(pState, pszFmt, "'%%M' does not support any size flags (%c)", chSize);
228 if (fFlags != 0)
229 VFmtChkWarnFmt(pState, pszFmt, "'%%M' does not support any format flags (%#x)", fFlags);
230 if (VFmtChkRequireStringArg(pState, pszPct, iArg, "'%M' expects a format string"))
231 VFmtChkHandleReplacementFormatString(pState, pszPct, iArg);
232 return;
233 }
234
235 case 'N': /* real nesting. */
236 {
237 if (chSize != '\0')
238 VFmtChkWarnFmt(pState, pszFmt, "'%%N' does not support any size flags (%c)", chSize);
239 if (fFlags != 0)
240 VFmtChkWarnFmt(pState, pszFmt, "'%%N' does not support any format flags (%#x)", fFlags);
241 VFmtChkRequireStringArg(pState, pszPct, iArg, "'%N' expects a string followed by a va_list pointer");
242 VFmtChkRequireVaListPtrArg(pState, pszPct, iArg + 1, "'%N' expects a string followed by a va_list pointer");
243 iArg += 2;
244 break;
245 }
246
247 default:
248 VFmtChkRequirePresentArg(pState, pszPct, iArg, "Expected argument");
249 iArg++;
250 break;
251 }
252 }
253}
254
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