cccp.c fix for VMS

Klaus Kaempf kkaempf@progis.de
Mon Jun 8 07:11:00 GMT 1998


The current include file handling on vms fails in files are
in sub-directories and accessed with 'include <subdir/file.h>'.

The following patch fixes this and cleans up hack_vms_include_specification().

Mon Jun  8 15:42:27 1998  Klaus Kaempf (kkaempf@progis.de)

	* cccp.c (hack_vms_include_specification): rewrite to handle
	'#include <dir/file.h>' correctly.

===================================================================
RCS file: RCS/cccp.c,v
retrieving revision 1.1
diff -c -r1.1 cccp.c
*** cccp.c	1998/06/08 12:06:28	1.1
--- cccp.c	1998/06/08 13:12:15
***************
*** 78,84 ****
  static int VMS_open ();
  static FILE *VMS_fopen ();
  static FILE *VMS_freopen ();
! static void hack_vms_include_specification ();
  #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
  #define INO_T_HASH(a) 0
  #define INCLUDE_LEN_FUDGE 12	/* leave room for VMS syntax conversion */
--- 78,84 ----
  static int VMS_open ();
  static FILE *VMS_fopen ();
  static FILE *VMS_freopen ();
! static int hack_vms_include_specification ();
  #define INO_T_EQ(a, b) (!bcmp((char *) &(a), (char *) &(b), sizeof (a)))
  #define INO_T_HASH(a) 0
  #define INCLUDE_LEN_FUDGE 12	/* leave room for VMS syntax conversion */
***************
*** 4327,4332 ****
--- 4327,4342 ----
  	    simplify_filename (dsp->fname);
  	    nam = base_name (dsp->fname);
  	    *nam = 0;
+ #ifdef VMS
+ 	    /* for hack_vms_include_specification(), a local
+ 	       dir specification must start with "./" on VMS.  */
+ 	    if (nam == dsp->fname)
+ 	      {    
+ 		*nam++ = '.';
+ 		*nam++ = '/';
+ 		*nam = 0;
+ 	      }
+ #endif
  	    /* But for efficiency's sake, do not insert the dir
  	       if it matches the search list's first dir.  */
  	    dsp->next = search_start;
***************
*** 4485,4506 ****
  	  }
        }
  
-       strcpy (fname, searchptr->fname);
-       strcat (fname, fbeg);
  #ifdef VMS
        /* Change this 1/2 Unix 1/2 VMS file specification into a
           full VMS file specification */
!       if (searchptr->fname[0]) {
! 	/* Fix up the filename */
! 	hack_vms_include_specification (fname, vaxc_include);
!       } else {
! 	/* This is a normal VMS filespec, so use it unchanged.  */
! 	strcpy (fname, fbeg);
! 	/* if it's '#include filename', add the missing .h */
! 	if (vaxc_include && index(fname,'.')==NULL) {
! 	  strcat (fname, ".h");
  	}
!       }
  #endif /* VMS */
        f = open_include_file (fname, searchptr, importing, &inc);
        if (f != -1) {
--- 4495,4531 ----
  	  }
        }
  
  #ifdef VMS
        /* Change this 1/2 Unix 1/2 VMS file specification into a
           full VMS file specification */
!       if (searchptr->fname[0])
! 	{
! 	  strcpy (fname, searchptr->fname);
! 	  if (fname[strlen (fname) - 1] == ':')
! 	    {
! 	      char *slashp;
! 	      slashp = strchr (fbeg, '/');
! 
! 	      /* start at root-dir of logical device if no path given.  */
! 	      if (slashp == 0)
! 		strcat (fname, "[000000]");
! 	    }
! 	  strcat (fname, fbeg);
! 
! 	  /* Fix up the filename */
! 	  hack_vms_include_specification (fname, vaxc_include);
  	}
!       else
! 	{
! 	  /* This is a normal VMS filespec, so use it unchanged.  */
! 	  strcpy (fname, fbeg);
! 	  /* if it's '#include filename', add the missing .h */
! 	  if (vaxc_include && index(fname,'.')==NULL)
! 	    strcat (fname, ".h");
! 	}
! #else
!       strcpy (fname, searchptr->fname);
!       strcat (fname, fbeg);
  #endif /* VMS */
        f = open_include_file (fname, searchptr, importing, &inc);
        if (f != -1) {
***************
*** 4688,4693 ****
--- 4713,4721 ----
    /* At present, any path that begins with a drive spec is absolute.  */
    if (ISALPHA (filename[0]) && filename[1] == ':') return 1;
  #endif
+ #ifdef VMS
+   if (index (filename, ':') != 0) return 1;
+ #endif
    if (filename[0] == '/') return 1;
  #ifdef DIR_SEPARATOR
    if (filename[0] == DIR_SEPARATOR) return 1;
***************
*** 4737,4745 ****
    to0 = to;
  
    for (;;) {
      if (from[0] == '.' && from[1] == '/')
        from += 2;
!     else {
        /* Copy this component and trailing /, if any.  */
        while ((*to++ = *from++) != '/') {
  	if (!to[-1]) {
--- 4765,4776 ----
    to0 = to;
  
    for (;;) {
+ #ifndef VMS
      if (from[0] == '.' && from[1] == '/')
        from += 2;
!     else
! #endif
!       {
        /* Copy this component and trailing /, if any.  */
        while ((*to++ = *from++) != '/') {
  	if (!to[-1]) {
***************
*** 4937,4943 ****
      fd = open (fname, O_RDONLY, 0);
  
      if (fd < 0)
!       return fd;
  
      if (!inc) {
        /* FNAME was not in include_hashtab; insert a new entry.  */
--- 4968,4983 ----
      fd = open (fname, O_RDONLY, 0);
  
      if (fd < 0)
!       {
! #ifdef VMS
! 	/* if #include <dir/file> fails, try again with hacked spec.  */
! 	if (!hack_vms_include_specification (fname, 0))
! 	  return fd;
! 	fd = open (fname, O_RDONLY, 0);
! 	if (fd < 0)
! #endif
! 	  return fd;
!       }
  
      if (!inc) {
        /* FNAME was not in include_hashtab; insert a new entry.  */
***************
*** 9976,9982 ****
--- 10016,10027 ----
        if (len == 1 && dir->fname[len - 1] == '.')
  	len = 0;
        else
+ #ifdef VMS
+ 	/* must be '/', hack_vms_include_specification triggers on it.  */
+ 	dir->fname[len++] = '/';
+ #else
  	dir->fname[len++] = DIR_SEPARATOR;
+ #endif
        dir->fname[len] = 0;
      }
  
***************
*** 10281,10311 ****
  
  #ifdef VMS
  
! /* Under VMS we need to fix up the "include" specification filename so
!    that everything following the 1st slash is changed into its correct
!    VMS file specification.  */
  
! static void
! hack_vms_include_specification (fname, vaxc_include)
!      char *fname;
       int vaxc_include;
  {
!   register char *cp, *cp1, *cp2;
!   int f, check_filename_before_returning;
    char Local[512];
  
    check_filename_before_returning = 0;
  
!   cp = base_name (fname);
  
    /*
     * Check if we have a vax-c style '#include filename'
     * and add the missing .h
     */
-   if (vaxc_include && !index (cp,'.'))
-     strcat (cp, ".h");
  
!   cp2 = Local;			/* initialize */
  
    /* We are trying to do a number of things here.  First of all, we are
       trying to hammer the filenames into a standard format, such that later
--- 10326,10409 ----
  
  #ifdef VMS
  
! /* Under VMS we need to fix up the "include" specification filename.
  
!    Rules for possible conversions
! 
! 	fullname		tried paths
! 
! 	name			name
! 	./dir/name		[.dir]name
! 	/dir/name		dir:name
! 	/name			[000000]name, name
! 	dir/name		dir:[000000]name, dir:name, dir/name
! 	dir1/dir2/name		dir1:[dir2]name, dir1:[000000.dir2]name
! 	path:/name		path:[000000]name, path:name
! 	path:/dir/name		path:[000000.dir]name, path:[dir]name
! 	path:dir/name		path:[dir]name
! 	[path]:[dir]name	[path.dir]name
! 	path/[dir]name		[path.dir]name
! 
!    The path:/name input is constructed when expanding <> includes.
! 
!    return 1 if name was changed, 0 else.  */
! 
! static int
! hack_vms_include_specification (fullname, vaxc_include)
!      char *fullname;
       int vaxc_include;
  {
!   register char *basename, *unixname, *local_ptr, *first_slash;
!   int f, check_filename_before_returning, must_revert;
    char Local[512];
  
    check_filename_before_returning = 0;
+   must_revert = 0;
+   /* See if we can find a 1st slash. If not, there's no path information.  */
+   first_slash = index (fullname, '/');
+   if (first_slash == 0)
+     return 0;				/* Nothing to do!!! */
+ 
+   /* construct device spec if none given.  */
+ 
+   if (index (fullname, ':') == 0)
+     {
+ 
+       /* If fullname has a slash, take it as device spec.  */
+ 
+       if (first_slash == fullname)
+ 	{
+ 	  first_slash = index (fullname+1, '/');	/* 2nd slash ? */
+ 	  if (first_slash)
+ 	    *first_slash = ':';				/* make device spec  */
+ 	  for (basename = fullname; *basename != 0; basename++)
+ 	    *basename = *(basename+1);			/* remove leading slash  */
+ 	}
+       else if ((first_slash[-1] != '.')		/* keep ':/', './' */
+ 	    && (first_slash[-1] != ':')
+ 	    && (first_slash[-1] != ']'))	/* or a vms path  */
+ 	{
+ 	  *first_slash = ':';
+ 	}
+       else if ((first_slash[1] == '[')		/* skip './' in './[dir'  */
+ 	    && (first_slash[-1] == '.'))
+ 	fullname += 2;
+     }
+ 
+   /* Get part after first ':' (basename[-1] == ':')
+      or last '/' (basename[-1] == '/').  */
  
!   basename = base_name (fullname);
  
    /*
     * Check if we have a vax-c style '#include filename'
     * and add the missing .h
     */
  
!   if (vaxc_include && !index (basename,'.'))
!     strcat (basename, ".h");
! 
!   local_ptr = Local;			/* initialize */
  
    /* We are trying to do a number of things here.  First of all, we are
       trying to hammer the filenames into a standard format, such that later
***************
*** 10318,10429 ****
       If no device is specified, then the first directory name is taken to be
       a device name (or a rooted logical).  */
  
!   /* See if we found that 1st slash */
!   if (cp == 0) return;		/* Nothing to do!!! */
!   if (*cp != '/') return;	/* Nothing to do!!! */
!   /* Point to the UNIX filename part (which needs to be fixed!) */
!   cp1 = cp+1;
    /* If the directory spec is not rooted, we can just copy
!      the UNIX filename part and we are done */
!   if (((cp - fname) > 1) && ((cp[-1] == ']') || (cp[-1] == '>'))) {
!     if (cp[-2] != '.') {
!       /*
!        * The VMS part ends in a `]', and the preceding character is not a `.'.
!        * We strip the `]', and then splice the two parts of the name in the
!        * usual way.  Given the default locations for include files in cccp.c,
!        * we will only use this code if the user specifies alternate locations
!        * with the /include (-I) switch on the command line.  */
!       cp -= 1;			/* Strip "]" */
!       cp1--;			/* backspace */
!     } else {
!       /*
!        * The VMS part has a ".]" at the end, and this will not do.  Later
!        * processing will add a second directory spec, and this would be a syntax
!        * error.  Thus we strip the ".]", and thus merge the directory specs.
!        * We also backspace cp1, so that it points to a '/'.  This inhibits the
!        * generation of the 000000 root directory spec (which does not belong here
!        * in this case).
!        */
!       cp -= 2;			/* Strip ".]" */
!       cp1--; };			/* backspace */
!   } else {
  
!     /* We drop in here if there is no VMS style directory specification yet.
!      * If there is no device specification either, we make the first dir a
!      * device and try that.  If we do not do this, then we will be essentially
!      * searching the users default directory (as if they did a #include "asdf.h").
!      *
!      * Then all we need to do is to push a '[' into the output string. Later
!      * processing will fill this in, and close the bracket.
!      */
!     if (cp[-1] != ':') *cp2++ = ':'; /* dev not in spec.  take first dir */
!     *cp2++ = '[';		/* Open the directory specification */
!   }
  
    /* at this point we assume that we have the device spec, and (at least
       the opening "[" for a directory specification.  We may have directories
!      specified already */
  
!   /* If there are no other slashes then the filename will be
       in the "root" directory.  Otherwise, we need to add
       directory specifications.  */
!   if (index (cp1, '/') == 0) {
!     /* Just add "000000]" as the directory string */
!     strcpy (cp2, "000000]");
!     cp2 += strlen (cp2);
!     check_filename_before_returning = 1; /* we might need to fool with this later */
!   } else {
!     /* As long as there are still subdirectories to add, do them.  */
!     while (index (cp1, '/') != 0) {
!       /* If this token is "." we can ignore it */
!       if ((cp1[0] == '.') && (cp1[1] == '/')) {
! 	cp1 += 2;
! 	continue;
!       }
!       /* Add a subdirectory spec. Do not duplicate "." */
!       if (cp2[-1] != '.' && cp2[-1] != '[' && cp2[-1] != '<')
! 	*cp2++ = '.';
!       /* If this is ".." then the spec becomes "-" */
!       if ((cp1[0] == '.') && (cp1[1] == '.') && (cp[2] == '/')) {
! 	/* Add "-" and skip the ".." */
! 	*cp2++ = '-';
! 	cp1 += 3;
! 	continue;
!       }
!       /* Copy the subdirectory */
!       while (*cp1 != '/') *cp2++= *cp1++;
!       cp1++;			/* Skip the "/" */
!     }
!     /* Close the directory specification */
!     if (cp2[-1] == '.')		/* no trailing periods */
!       cp2--;
!     *cp2++ = ']';
!   }
!   /* Now add the filename */
!   while (*cp1) *cp2++ = *cp1++;
!   *cp2 = 0;
    /* Now append it to the original VMS spec.  */
!   strcpy (cp, Local);
  
    /* If we put a [000000] in the filename, try to open it first. If this fails,
       remove the [000000], and return that name.  This provides flexibility
       to the user in that they can use both rooted and non-rooted logical names
       to point to the location of the file.  */
  
!   if (check_filename_before_returning) {
!     f = open (fname, O_RDONLY, 0666);
!     if (f >= 0) {
!       /* The file name is OK as it is, so return it as is.  */
!       close (f);
!       return;
      }
!     /* The filename did not work.  Try to remove the [000000] from the name,
!        and return it.  */
!     cp = index (fname, '[');
!     cp2 = index (fname, ']') + 1;
!     strcpy (cp, cp2);		/* this gets rid of it */
!   }
!   return;
  }
  #endif	/* VMS */
  
--- 10416,10610 ----
       If no device is specified, then the first directory name is taken to be
       a device name (or a rooted logical).  */
  
!   /* Point to the UNIX filename part (which needs to be fixed!)
!      but skip vms path information.
!      [basename != fullname since first_slash != 0].  */
! 
!   if ((basename[-1] == ':')		/* vms path spec.  */
!       || (basename[-1] == ']')
!       || (basename[-1] == '>'))
!     unixname = basename;
!   else
!     unixname = fullname;
! 
!   if (*unixname == '/')
!     unixname++;
! 
    /* If the directory spec is not rooted, we can just copy
!      the UNIX filename part and we are done.  */
  
!   if (((basename - fullname) > 1)
!      && (  (basename[-1] == ']')
!         || (basename[-1] == '>')))
!     {
!       if (basename[-2] != '.')
! 	{
! 
! 	/* The VMS part ends in a `]', and the preceding character is not a `.'.
! 	   -> PATH]:/name (basename = '/name', unixname = 'name')
! 	   We strip the `]', and then splice the two parts of the name in the
! 	   usual way.  Given the default locations for include files in cccp.c,
! 	   we will only use this code if the user specifies alternate locations
! 	   with the /include (-I) switch on the command line.  */
! 
! 	  basename -= 1;	/* Strip "]" */
! 	  unixname--;		/* backspace */
! 	}
!       else
! 	{
! 
! 	/* The VMS part has a ".]" at the end, and this will not do.  Later
! 	   processing will add a second directory spec, and this would be a syntax
! 	   error.  Thus we strip the ".]", and thus merge the directory specs.
! 	   We also backspace unixname, so that it points to a '/'.  This inhibits the
! 	   generation of the 000000 root directory spec (which does not belong here
! 	   in this case).  */
! 
! 	  basename -= 2;	/* Strip ".]" */
! 	  unixname--;		/* backspace */
! 	}
!     }
! 
!   else
! 
!     {
! 
!       /* We drop in here if there is no VMS style directory specification yet.
!          If there is no device specification either, we make the first dir a
!          device and try that.  If we do not do this, then we will be essentially
!          searching the users default directory (as if they did a #include "asdf.h").
!         
!          Then all we need to do is to push a '[' into the output string. Later
!          processing will fill this in, and close the bracket.  */
! 
!       if ((unixname != fullname)	/* vms path spec found.  */
! 	 && (basename[-1] != ':'))
! 	*local_ptr++ = ':';		/* dev not in spec.  take first dir */
! 
!       *local_ptr++ = '[';		/* Open the directory specification */
!     }
! 
!     if (unixname == fullname)		/* no vms dir spec.  */
!       {
! 	must_revert = 1;
! 	if ((first_slash != 0)		/* unix dir spec.  */
! 	    && (*unixname != '/')	/* not beginning with '/'  */
! 	    && (*unixname != '.'))	/* or './' or '../'  */
! 	  *local_ptr++ = '.';		/* dir is local !  */
!       }
  
    /* at this point we assume that we have the device spec, and (at least
       the opening "[" for a directory specification.  We may have directories
!      specified already.
  
!      If there are no other slashes then the filename will be
       in the "root" directory.  Otherwise, we need to add
       directory specifications.  */
! 
!   if (index (unixname, '/') == 0)
!     {
!       /* if no directories specified yet and none are following.  */
!       if (local_ptr[-1] == '[')
! 	{
! 	  /* Just add "000000]" as the directory string */
! 	  strcpy (local_ptr, "000000]");
! 	  local_ptr += strlen (local_ptr);
! 	  check_filename_before_returning = 1; /* we might need to fool with this later */
! 	}
!     }
!   else
!     {
! 
!       /* As long as there are still subdirectories to add, do them.  */
!       while (index (unixname, '/') != 0)
! 	{
! 	  /* If this token is "." we can ignore it
! 	       if it's not at the beginning of a path.  */
! 	  if ((unixname[0] == '.') && (unixname[1] == '/'))
! 	    {
! 	      /* remove it at beginning of path.  */
! 	      if (  ((unixname == fullname)		/* no device spec  */
! 		    && (fullname+2 != basename))	/* starts with ./ */
! 							/* or  */
! 		 || ((basename[-1] == ':')		/* device spec  */
! 		    && (unixname-1 == basename)))	/* and ./ afterwards  */
! 		*local_ptr++ = '.';		 	/* make '[.' start of path.  */
! 	      unixname += 2;
! 	      continue;
! 	    }
! 
! 	  /* Add a subdirectory spec. Do not duplicate "." */
! 	  if (  local_ptr[-1] != '.'
! 	     && local_ptr[-1] != '['
! 	     && local_ptr[-1] != '<')
! 	    *local_ptr++ = '.';
! 
! 	  /* If this is ".." then the spec becomes "-" */
! 	  if (  (unixname[0] == '.')
! 	     && (unixname[1] == '.')
! 	     && (unixname[2] == '/'))
! 	    {
! 	      /* Add "-" and skip the ".." */
! 	      if ((local_ptr[-1] == '.')
! 		  && (local_ptr[-2] == '['))
! 		local_ptr--;			/* prevent [.-  */
! 	      *local_ptr++ = '-';
! 	      unixname += 3;
! 	      continue;
! 	    }
! 
! 	  /* Copy the subdirectory */
! 	  while (*unixname != '/')
! 	    *local_ptr++= *unixname++;
! 
! 	  unixname++;			/* Skip the "/" */
! 	}
! 
!       /* Close the directory specification */
!       if (local_ptr[-1] == '.')		/* no trailing periods */
! 	local_ptr--;
! 
!       if (local_ptr[-1] == '[')		/* no dir needed */
! 	local_ptr--;
!       else
! 	*local_ptr++ = ']';
!     }
! 
!   /* Now add the filename.  */
! 
!   while (*unixname)
!     *local_ptr++ = *unixname++;
!   *local_ptr = 0;
! 
    /* Now append it to the original VMS spec.  */
! 
!   strcpy ((must_revert==1)?fullname:basename, Local);
  
    /* If we put a [000000] in the filename, try to open it first. If this fails,
       remove the [000000], and return that name.  This provides flexibility
       to the user in that they can use both rooted and non-rooted logical names
       to point to the location of the file.  */
  
!   if (check_filename_before_returning)
!     {
!       f = open (fullname, O_RDONLY, 0666);
!       if (f >= 0)
! 	{
! 	  /* The file name is OK as it is, so return it as is.  */
! 	  close (f);
! 	  return 1;
! 	}
! 
!       /* The filename did not work.  Try to remove the [000000] from the name,
! 	 and return it.  */
! 
!       basename = index (fullname, '[');
!       local_ptr = index (fullname, ']') + 1;
!       strcpy (basename, local_ptr);		/* this gets rid of it */
! 
      }
! 
!   return 1;
  }
  #endif	/* VMS */
  

-- 
proGIS Software                 E-Mail: kkaempf@progis.de
Dipl.-Inform. Klaus K"ampf      Fax:    0241-47067-29
Jakobstr. 117                   Voice:  0241-47067-11
D-52064 Aachen                  WWW:	http://www.progis.de




More information about the Gcc-patches mailing list