VirtualBox

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

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

gccplugin: Use error_at instead of warning_at when there are too many or too few arguments. Implemented %M.

  • 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 57002 2015-07-18 23:44:13Z 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 ch = *pszFmt++;
121 }
122
123 /*
124 * Precision
125 */
126 int cchPrecision = -1;
127 if (ch == '.')
128 {
129 ch = *pszFmt++;
130 if (MY_ISDIGIT(ch))
131 {
132 cchPrecision = ch - '0';
133 while ( (ch = *pszFmt++) != '\0'
134 && MY_ISDIGIT(ch))
135 {
136 cchPrecision *= 10;
137 cchPrecision += ch - '0';
138 }
139 }
140 else if (ch == '*')
141 {
142 VFmtChkRequireIntArg(pState, pszPct, iArg, "precision should be an 'int' sized argument");
143 iArg++;
144 cchPrecision = 0;
145 ch = *pszFmt++;
146 }
147 else
148 VFmtChkErrFmt(pState, pszPct, "Missing precision value, only got the '.'");
149 if (cchPrecision < 0)
150 {
151 VFmtChkErrFmt(pState, pszPct, "Negative precision value: %d", cchPrecision);
152 cchPrecision = 0;
153 }
154 fFlags |= RTSTR_F_PRECISION;
155 }
156
157 /*
158 * Argument size.
159 */
160 char chSize = ch;
161 switch (ch)
162 {
163 default:
164 chSize = '\0';
165 break;
166
167 case 'z':
168 case 'L':
169 case 'j':
170 case 't':
171 ch = *pszFmt++;
172 break;
173
174 case 'l':
175 ch = *pszFmt++;
176 if (ch == 'l')
177 {
178 chSize = 'L';
179 ch = *pszFmt++;
180 }
181 break;
182
183 case 'h':
184 ch = *pszFmt++;
185 if (ch == 'h')
186 {
187 chSize = 'H';
188 ch = *pszFmt++;
189 }
190 break;
191
192 case 'I': /* Used by Win32/64 compilers. */
193 if ( pszFmt[0] == '6'
194 && pszFmt[1] == '4')
195 {
196 pszFmt += 2;
197 chSize = 'L';
198 }
199 else if ( pszFmt[0] == '3'
200 && pszFmt[1] == '2')
201 {
202 pszFmt += 2;
203 chSize = 0;
204 }
205 else
206 chSize = 'j';
207 ch = *pszFmt++;
208 break;
209
210 case 'q': /* Used on BSD platforms. */
211 chSize = 'L';
212 ch = *pszFmt++;
213 break;
214 }
215
216 /*
217 * The type.
218 */
219 switch (ch)
220 {
221 /*
222 * Nested extensions.
223 */
224 case 'M': /* replace the format string (not stacked yet). */
225 {
226 if (*pszFmt)
227 VFmtChkErrFmt(pState, pszFmt, "Characters following '%%M' will be ignored");
228 if (chSize != '\0')
229 VFmtChkWarnFmt(pState, pszFmt, "'%%M' does not support any size flags (%c)", chSize);
230 if (fFlags != 0)
231 VFmtChkWarnFmt(pState, pszFmt, "'%%M' does not support any format flags (%#x)", fFlags);
232 if (VFmtChkRequireStringArg(pState, pszPct, iArg, "'%M' expects a format string"))
233 VFmtChkHandleReplacementFormatString(pState, pszPct, iArg);
234 return;
235 }
236
237 case 'N': /* real nesting. */
238 {
239 if (chSize != '\0')
240 VFmtChkWarnFmt(pState, pszFmt, "'%%N' does not support any size flags (%c)", chSize);
241 if (fFlags != 0)
242 VFmtChkWarnFmt(pState, pszFmt, "'%%N' does not support any format flags (%#x)", fFlags);
243 VFmtChkRequireStringArg(pState, pszPct, iArg, "'%N' expects a string followed by a va_list pointer");
244 VFmtChkRequireVaListPtrArg(pState, pszPct, iArg + 1, "'%N' expects a string followed by a va_list pointer");
245 iArg += 2;
246 break;
247 }
248
249 default:
250 VFmtChkRequirePresentArg(pState, pszPct, iArg, "Expected argument");
251 iArg++;
252 break;
253 }
254 }
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