1/* VMS specific, C compiler specific functions.
2   Copyright (C) 2011-2015 Free Software Foundation, Inc.
3   Contributed by Tristan Gingold (gingold@adacore.com).
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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 "tm.h"
25#include "cpplib.h"
26#include "hash-set.h"
27#include "machmode.h"
28#include "vec.h"
29#include "double-int.h"
30#include "input.h"
31#include "alias.h"
32#include "symtab.h"
33#include "wide-int.h"
34#include "inchash.h"
35#include "tree.h"
36#include "c-family/c-pragma.h"
37#include "c-family/c-common.h"
38#include "c/c-tree.h"
39#include "toplev.h"
40#include "ggc.h"
41#include "tm_p.h"
42#include "incpath.h"
43#include "diagnostic.h"
44
45/* '#pragma __nostandard' is simply ignored.  */
46
47static void
48vms_pragma_nostandard (cpp_reader *pfile ATTRIBUTE_UNUSED)
49{
50  tree x;
51
52  if (pragma_lex (&x) != CPP_EOF)
53    warning (OPT_Wpragmas, "junk at end of #pragma __nostandard");
54}
55
56/* '#pragma __standard' is simply ignored.  */
57
58static void
59vms_pragma_standard (cpp_reader *pfile ATTRIBUTE_UNUSED)
60{
61  tree x;
62
63  if (pragma_lex (&x) != CPP_EOF)
64    warning (OPT_Wpragmas, "junk at end of #pragma __standard");
65}
66
67/* Saved member alignment.  */
68static int saved_member_alignment;
69
70/* Handle '#pragma member_alignment'.  */
71
72static void
73vms_pragma_member_alignment (cpp_reader *pfile ATTRIBUTE_UNUSED)
74{
75  tree x;
76  int tok;
77  const char *arg;
78
79  tok = pragma_lex (&x);
80
81  if (tok == CPP_EOF)
82    {
83      /* Disable packing.  */
84      maximum_field_alignment = initial_max_fld_align;
85      return;
86    }
87  if (tok != CPP_NAME)
88    {
89      warning (OPT_Wpragmas, "malformed '#pragma member_alignment', ignoring");
90      return;
91    }
92
93  arg = IDENTIFIER_POINTER (x);
94  /* Accept '__' prefix.  */
95  if (arg[0] == '_' && arg[1] == '_')
96    arg += 2;
97
98  if (strcmp (arg, "save") == 0)
99    saved_member_alignment = maximum_field_alignment;
100  else if (strcmp (arg, "restore") == 0)
101    maximum_field_alignment = saved_member_alignment;
102  else
103    {
104      error ("unknown '#pragma member_alignment' name %s", arg);
105      return;
106    }
107  if (pragma_lex (&x) != CPP_EOF)
108    {
109      error ("malformed '#pragma member_alignment'");
110      return;
111    }
112}
113
114/* Handle '#pragma nomember_alignment'.  */
115
116static void
117vms_pragma_nomember_alignment (cpp_reader *pfile ATTRIBUTE_UNUSED)
118{
119  tree x;
120  int tok;
121
122  tok = pragma_lex (&x);
123  if (tok == CPP_NAME)
124    {
125      const char *arg = IDENTIFIER_POINTER (x);
126
127      /* Accept '__' prefix.  */
128      if (arg[0] == '_' && arg[1] == '_')
129        arg += 2;
130
131      if (strcmp (arg, "byte") == 0)
132        maximum_field_alignment = 1 * BITS_PER_UNIT;
133      else if (strcmp (arg, "word") == 0)
134        maximum_field_alignment = 2 * BITS_PER_UNIT;
135      else if (strcmp (arg, "longword") == 0)
136        maximum_field_alignment = 4 * BITS_PER_UNIT;
137      else if (strcmp (arg, "quadword") == 0)
138        maximum_field_alignment = 8 * BITS_PER_UNIT;
139      else if (strcmp (arg, "octaword") == 0)
140        maximum_field_alignment = 16 * BITS_PER_UNIT;
141      else
142        {
143          error ("unhandled alignment for '#pragma nomember_alignment'");
144        }
145
146      tok = pragma_lex (&x);
147    }
148  else
149    {
150      /* Enable packing.  */
151      maximum_field_alignment = BITS_PER_UNIT;
152    }
153
154  if (tok != CPP_EOF)
155    {
156      error ("garbage at end of '#pragma nomember_alignment'");
157      return;
158    }
159}
160
161/* The 'extern model' for public data.  This drives how the following
162   declarations are handled:
163   1) extern int name;
164   2) int name;
165   3) int name = 5;
166   See below for the behaviour as implemented by the native compiler.
167*/
168
169enum extern_model_kind
170{
171  /* Create one overlaid section per variable.  All the above declarations (1,
172      2 and 3) are handled the same way: they create an overlaid section named
173      NAME (and initialized only for 3).  No global symbol is created.
174      This is the VAX C behavior.  */
175  extern_model_common_block,
176
177  /* Like unix: multiple not-initialized declarations are allowed.
178     Only one initialized definition (case 3) is allows, but multiple
179     uninitialize definition (case 2) are allowed.
180     For case 2, this creates both a section named NAME and a global symbol.
181     For case 3, this creates a conditional global symbol defenition and a
182     conditional section definition.
183     This is the traditional UNIX C behavior.  */
184  extern_model_relaxed_refdef,
185
186  /* Like -fno-common.  Only one definition (cases 2 and 3) are allowed.
187     This is the ANSI-C model.  */
188  extern_model_strict_refdef,
189
190  /* Declarations creates symbols without storage.  */
191  extern_model_globalvalue
192};
193
194/* Current and saved extern model.  */
195static enum extern_model_kind current_extern_model;
196static enum extern_model_kind saved_extern_model;
197
198/* Partial handling of '#pragma extern_model'.  */
199
200static void
201vms_pragma_extern_model (cpp_reader *pfile ATTRIBUTE_UNUSED)
202{
203  tree x;
204  int tok;
205  const char *arg;
206
207  tok = pragma_lex (&x);
208
209  if (tok != CPP_NAME)
210    {
211      warning (OPT_Wpragmas, "malformed '#pragma extern_model', ignoring");
212      return;
213    }
214
215  arg = IDENTIFIER_POINTER (x);
216  /* Accept "__" prefix.  */
217  if (arg[0] == '_' && arg[1] == '_')
218    arg += 2;
219
220  if (strcmp (arg, "save") == 0)
221    saved_extern_model = current_extern_model;
222  else if (strcmp (arg, "restore") == 0)
223    current_extern_model = saved_extern_model;
224  else if (strcmp (arg, "relaxed_refdef") == 0)
225    current_extern_model = extern_model_relaxed_refdef;
226  else if (strcmp (arg, "strict_refdef") == 0)
227    current_extern_model = extern_model_strict_refdef;
228  else if (strcmp (arg, "common_block") == 0)
229    current_extern_model = extern_model_common_block;
230  else if (strcmp (arg, "globalvalue") == 0)
231    {
232      sorry ("extern model globalvalue");
233      return;
234    }
235  else
236    {
237      error ("unknown '#pragma extern_model' model '%s'", arg);
238      return;
239    }
240#if 0
241  if (pragma_lex (&x) != CPP_EOF)
242    {
243      permerror (input_location, "junk at end of '#pragma extern_model'");
244      return;
245    }
246#endif
247}
248
249/* Ignore '#pragma message'.  */
250
251static void
252vms_pragma_message (cpp_reader *pfile ATTRIBUTE_UNUSED)
253{
254  /* Completly ignored.  */
255#if 0
256  pedwarn (input_location, OPT_Wpragmas,
257           "vms '#pragma __message' is ignored");
258#endif
259}
260
261/* Handle '#pragma __extern_prefix'  */
262
263static GTY(()) tree saved_extern_prefix;
264
265static void
266vms_pragma_extern_prefix (cpp_reader * ARG_UNUSED (dummy))
267{
268  enum cpp_ttype tok;
269  tree x;
270
271  tok = pragma_lex (&x);
272  if (tok == CPP_NAME)
273    {
274      const char *op = IDENTIFIER_POINTER (x);
275
276      if (!strcmp (op, "__save"))
277        saved_extern_prefix = pragma_extern_prefix;
278      else if (!strcmp (op, "__restore"))
279        pragma_extern_prefix = saved_extern_prefix;
280      else
281        warning (OPT_Wpragmas,
282                 "malformed '#pragma __extern_prefix', ignoring");
283      return;
284    }
285  else if (tok != CPP_STRING)
286    {
287      warning (OPT_Wpragmas,
288               "malformed '#pragma __extern_prefix', ignoring");
289    }
290  else
291    {
292      /* Note that the length includes the null terminator.  */
293      pragma_extern_prefix = (TREE_STRING_LENGTH (x) > 1 ? x : NULL);
294    }
295}
296
297/* #pragma __pointer_size  */
298
299static machine_mode saved_pointer_mode;
300
301static void
302handle_pragma_pointer_size (const char *pragma_name)
303{
304  enum cpp_ttype tok;
305  tree x;
306
307  tok = pragma_lex (&x);
308  if (tok == CPP_NAME)
309    {
310      const char *op = IDENTIFIER_POINTER (x);
311
312      if (!strcmp (op, "__save"))
313        saved_pointer_mode = c_default_pointer_mode;
314      else if (!strcmp (op, "__restore"))
315        c_default_pointer_mode = saved_pointer_mode;
316      else if (!strcmp (op, "__short"))
317        c_default_pointer_mode = SImode;
318      else if (!strcmp (op, "__long"))
319        c_default_pointer_mode = DImode;
320      else
321        error ("malformed %<#pragma %s%>, ignoring", pragma_name);
322    }
323  else if (tok == CPP_NUMBER)
324    {
325      int val;
326
327      if (TREE_CODE (x) == INTEGER_CST)
328        val = TREE_INT_CST_LOW (x);
329      else
330        val = -1;
331
332      if (val == 32)
333        c_default_pointer_mode = SImode;
334      else if (val == 64)
335        c_default_pointer_mode = DImode;
336      else
337        error ("invalid constant in %<#pragma %s%>", pragma_name);
338    }
339  else
340    {
341      error ("malformed %<#pragma %s%>, ignoring", pragma_name);
342    }
343}
344
345static void
346vms_pragma_pointer_size (cpp_reader * ARG_UNUSED (dummy))
347{
348  /* Ignore if no -mpointer-size option.  */
349  if (flag_vms_pointer_size == VMS_POINTER_SIZE_NONE)
350    return;
351
352  handle_pragma_pointer_size ("pointer_size");
353}
354
355static void
356vms_pragma_required_pointer_size (cpp_reader * ARG_UNUSED (dummy))
357{
358  handle_pragma_pointer_size ("required_pointer_size");
359}
360
361/* Add vms-specific pragma.  */
362
363void
364vms_c_register_pragma (void)
365{
366  c_register_pragma (NULL, "__nostandard", vms_pragma_nostandard);
367  c_register_pragma (NULL, "nostandard", vms_pragma_nostandard);
368  c_register_pragma (NULL, "__standard", vms_pragma_standard);
369  c_register_pragma (NULL, "standard", vms_pragma_standard);
370  c_register_pragma (NULL, "__member_alignment", vms_pragma_member_alignment);
371  c_register_pragma (NULL, "member_alignment", vms_pragma_member_alignment);
372  c_register_pragma_with_expansion (NULL, "__nomember_alignment",
373                                    vms_pragma_nomember_alignment);
374  c_register_pragma_with_expansion (NULL, "nomember_alignment",
375                                    vms_pragma_nomember_alignment);
376  c_register_pragma (NULL, "__pointer_size",
377                     vms_pragma_pointer_size);
378  c_register_pragma (NULL, "__required_pointer_size",
379                     vms_pragma_required_pointer_size);
380  c_register_pragma (NULL, "__extern_model", vms_pragma_extern_model);
381  c_register_pragma (NULL, "extern_model", vms_pragma_extern_model);
382  c_register_pragma (NULL, "__message", vms_pragma_message);
383  c_register_pragma (NULL, "__extern_prefix", vms_pragma_extern_prefix);
384}
385
386/* Canonicalize the filename (remove directory prefix, force the .h extension),
387   and append it to the directory to create the path, but don't
388   turn / into // or // into ///; // may be a namespace escape.  */
389
390static char *
391vms_construct_include_filename (const char *fname, cpp_dir *dir)
392{
393  size_t dlen, flen;
394  char *path;
395  const char *fbasename = lbasename (fname);
396  size_t i;
397
398  dlen = dir->len;
399  flen = strlen (fbasename) + 2;
400  path = XNEWVEC (char, dlen + 1 + flen + 1);
401  memcpy (path, dir->name, dlen);
402  if (dlen && !IS_DIR_SEPARATOR (path[dlen - 1]))
403    path[dlen++] = '/';
404  for (i = 0; i < flen; i++)
405    if (fbasename[i] == '.')
406      break;
407    else
408      path[dlen + i] = TOLOWER (fbasename[i]);
409  path[dlen + i + 0] = '.';
410  path[dlen + i + 1] = 'h';
411  path[dlen + i + 2] = 0;
412
413  return path;
414}
415
416/* Standard modules list.  */
417static const char * const vms_std_modules[] = { "rtldef", "starlet_c", NULL };
418
419/* Find include modules in the include path.  */
420
421void
422vms_c_register_includes (const char *sysroot,
423                         const char *iprefix ATTRIBUTE_UNUSED, int stdinc)
424{
425  static const char dir_separator_str[] = { DIR_SEPARATOR, 0 };
426  struct cpp_dir *dir;
427
428  /* Add on standard include pathes.  */
429  if (!stdinc)
430    return;
431
432  for (dir = get_added_cpp_dirs (SYSTEM); dir != NULL; dir = dir->next)
433    {
434      const char * const *lib;
435      for (lib = vms_std_modules; *lib != NULL; lib++)
436        {
437          char *path;
438          struct stat st;
439
440          if (sysroot != NULL)
441            path = concat (sysroot, dir->name, dir_separator_str, *lib, NULL);
442          else
443            path = concat (dir->name, dir_separator_str, *lib, NULL);
444
445          if (stat (path, &st) == 0 && S_ISDIR (st.st_mode))
446            {
447              cpp_dir *p;
448
449              p = XNEW (cpp_dir);
450              p->next = NULL;
451              p->name = path;
452              p->sysp = 1;
453              p->construct = vms_construct_include_filename;
454              p->user_supplied_p = 0;
455              add_cpp_dir_path (p, SYSTEM);
456            }
457          else
458            free (path);
459        }
460    }
461}
462
463void
464vms_c_common_override_options (void)
465{
466  /* Allow variadic functions without parameters (as declared in starlet).  */
467  flag_allow_parameterless_variadic_functions = TRUE;
468
469  /* Initialize c_default_pointer_mode.  */
470  switch (flag_vms_pointer_size)
471    {
472    case VMS_POINTER_SIZE_NONE:
473      break;
474    case VMS_POINTER_SIZE_32:
475      c_default_pointer_mode = SImode;
476      break;
477    case VMS_POINTER_SIZE_64:
478      c_default_pointer_mode = DImode;
479      break;
480    }
481}
482
483/* The default value for _CRTL_VER macro.  */
484
485int
486vms_c_get_crtl_ver (void)
487{
488  return VMS_DEFAULT_CRTL_VER;
489}
490
491/* The default value for _VMS_VER macro.  */
492
493int
494vms_c_get_vms_ver (void)
495{
496  return VMS_DEFAULT_VMS_VER;
497}
498