1 /* Solaris support needed only by C/C++ frontends. 2 Copyright (C) 2004, 2005, 2007, 2009, 2010 Free Software Foundation, Inc. 3 Contributed by CodeSourcery, LLC. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "tree.h" 25 #include "tm.h" 26 #include "tm_p.h" 27 #include "toplev.h" 28 29 #include "c-format.h" 30 #include "intl.h" 31 32 #include "cpplib.h" 33 #include "c-pragma.h" 34 #include "c-common.h" 35 36 /* cmn_err only accepts "l" and "ll". */ 37 static const format_length_info cmn_err_length_specs[] = 38 { 39 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 }, 40 { NULL, FMT_LEN_none, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 } 41 }; 42 43 static const format_flag_spec cmn_err_flag_specs[] = 44 { 45 { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, 46 { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, 47 { 0, 0, 0, NULL, NULL, STD_C89 } 48 }; 49 50 51 static const format_flag_pair cmn_err_flag_pairs[] = 52 { 53 { 0, 0, 0, 0 } 54 }; 55 56 static const format_char_info bitfield_string_type = 57 { "b", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }; 58 59 static const format_char_info cmn_err_char_table[] = 60 { 61 /* C89 conversion specifiers. */ 62 { "dD", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 63 { "oOxX",0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 64 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 65 { "c", 0, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 66 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "c", NULL }, 67 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "cR", NULL }, 68 { "b", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", &bitfield_string_type }, 69 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } 70 }; 71 72 const format_kind_info solaris_format_types[] = { 73 { "cmn_err", cmn_err_length_specs, cmn_err_char_table, "", NULL, 74 cmn_err_flag_specs, cmn_err_flag_pairs, 75 FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK, 76 'w', 0, 0, 0, 'L', 0, 77 &integer_type_node, &integer_type_node 78 } 79 }; 80 81 /* Handle #pragma align ALIGNMENT (VAR [, VAR]...) */ 82 83 static void 84 solaris_pragma_align (cpp_reader *pfile ATTRIBUTE_UNUSED) 85 { 86 tree t, x; 87 enum cpp_ttype ttype; 88 HOST_WIDE_INT low; 89 90 if (pragma_lex (&x) != CPP_NUMBER 91 || pragma_lex (&t) != CPP_OPEN_PAREN) 92 { 93 warning (0, "malformed %<#pragma align%>, ignoring"); 94 return; 95 } 96 97 low = TREE_INT_CST_LOW (x); 98 if (TREE_INT_CST_HIGH (x) != 0 99 || (low != 1 && low != 2 && low != 4 && low != 8 && low != 16 100 && low != 32 && low != 64 && low != 128)) 101 { 102 warning (0, "invalid alignment for %<#pragma align%>, ignoring"); 103 return; 104 } 105 106 ttype = pragma_lex (&t); 107 if (ttype != CPP_NAME) 108 { 109 warning (0, "malformed %<#pragma align%>, ignoring"); 110 return; 111 } 112 113 while (1) 114 { 115 tree decl = identifier_global_value (t); 116 if (decl && DECL_P (decl)) 117 warning (0, "%<#pragma align%> must appear before the declaration of " 118 "%D, ignoring", decl); 119 else 120 solaris_pending_aligns = tree_cons (t, build_tree_list (NULL, x), 121 solaris_pending_aligns); 122 123 ttype = pragma_lex (&t); 124 if (ttype == CPP_COMMA) 125 { 126 ttype = pragma_lex (&t); 127 if (ttype != CPP_NAME) 128 { 129 warning (0, "malformed %<#pragma align%>"); 130 return; 131 } 132 } 133 else if (ttype == CPP_CLOSE_PAREN) 134 { 135 if (pragma_lex (&t) != CPP_EOF) 136 warning (0, "junk at end of %<#pragma align%>"); 137 return; 138 } 139 else 140 { 141 warning (0, "malformed %<#pragma align%>"); 142 return; 143 } 144 } 145 } 146 147 /* Handle #pragma init (function [, function]...) */ 148 149 static void 150 solaris_pragma_init (cpp_reader *pfile ATTRIBUTE_UNUSED) 151 { 152 tree t; 153 enum cpp_ttype ttype; 154 155 if (pragma_lex (&t) != CPP_OPEN_PAREN) 156 { 157 warning (0, "malformed %<#pragma init%>, ignoring"); 158 return; 159 } 160 161 ttype = pragma_lex (&t); 162 if (ttype != CPP_NAME) 163 { 164 warning (0, "malformed %<#pragma init%>, ignoring"); 165 return; 166 } 167 168 while (1) 169 { 170 tree decl = identifier_global_value (t); 171 if (decl && DECL_P (decl)) 172 { 173 tree attrs = build_tree_list (get_identifier ("init"), 174 NULL); 175 TREE_USED (decl) = 1; 176 DECL_PRESERVE_P (decl) = 1; 177 decl_attributes (&decl, attrs, 0); 178 } 179 else 180 solaris_pending_inits = tree_cons (t, NULL, solaris_pending_inits); 181 182 ttype = pragma_lex (&t); 183 if (ttype == CPP_COMMA) 184 { 185 ttype = pragma_lex (&t); 186 if (ttype != CPP_NAME) 187 { 188 warning (0, "malformed %<#pragma init%>"); 189 return; 190 } 191 } 192 else if (ttype == CPP_CLOSE_PAREN) 193 { 194 if (pragma_lex (&t) != CPP_EOF) 195 warning (0, "junk at end of %<#pragma init%>"); 196 return; 197 } 198 else 199 { 200 warning (0, "malformed %<#pragma init%>"); 201 return; 202 } 203 } 204 } 205 206 /* Handle #pragma fini (function [, function]...) */ 207 208 static void 209 solaris_pragma_fini (cpp_reader *pfile ATTRIBUTE_UNUSED) 210 { 211 tree t; 212 enum cpp_ttype ttype; 213 214 if (pragma_lex (&t) != CPP_OPEN_PAREN) 215 { 216 warning (0, "malformed %<#pragma fini%>, ignoring"); 217 return; 218 } 219 220 ttype = pragma_lex (&t); 221 if (ttype != CPP_NAME) 222 { 223 warning (0, "malformed %<#pragma fini%>, ignoring"); 224 return; 225 } 226 227 while (1) 228 { 229 tree decl = identifier_global_value (t); 230 if (decl && DECL_P (decl)) 231 { 232 tree attrs = build_tree_list (get_identifier ("fini"), 233 NULL); 234 TREE_USED (decl) = 1; 235 DECL_PRESERVE_P (decl) = 1; 236 decl_attributes (&decl, attrs, 0); 237 } 238 else 239 solaris_pending_finis = tree_cons (t, NULL, solaris_pending_finis); 240 241 ttype = pragma_lex (&t); 242 if (ttype == CPP_COMMA) 243 { 244 ttype = pragma_lex (&t); 245 if (ttype != CPP_NAME) 246 { 247 warning (0, "malformed %<#pragma fini%>"); 248 return; 249 } 250 } 251 else if (ttype == CPP_CLOSE_PAREN) 252 { 253 if (pragma_lex (&t) != CPP_EOF) 254 warning (0, "junk at end of %<#pragma fini%>"); 255 return; 256 } 257 else 258 { 259 warning (0, "malformed %<#pragma fini%>"); 260 return; 261 } 262 } 263 } 264 265 /* Register Solaris-specific #pragma directives. */ 266 267 void 268 solaris_register_pragmas (void) 269 { 270 c_register_pragma_with_expansion (0, "align", solaris_pragma_align); 271 c_register_pragma (0, "init", solaris_pragma_init); 272 c_register_pragma (0, "fini", solaris_pragma_fini); 273 } 274