The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

pathvms.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
00003  *
00004  * This file is part of Jam - see jam.c for Copyright information.
00005  */
00006 
00007 /*  This file is ALSO:
00008  *  (C) Copyright David Abrahams 2001. Permission to copy, use,
00009  *  modify, sell and distribute this software is granted provided this
00010  *  copyright notice appears in all copies. This software is provided
00011  *  "as is" without express or implied warranty, and with no claim as
00012  *  to its suitability for any purpose.
00013  */
00014 
00015 # include "jam.h"
00016 # include "pathsys.h"
00017 
00018 # ifdef OS_VMS
00019 
00020 # define DEBUG
00021 
00022 /*
00023  * pathvms.c - manipulate file names on VMS
00024  *
00025  * External routines:
00026  *
00027  *      path_parse() - split a file name into dir/base/suffix/member
00028  *      path_build() - build a filename given dir/base/suffix/member
00029  *      path_parent() - make a PATHNAME point to its parent dir
00030  *
00031  * File_parse() and path_build() just manipuate a string and a structure;
00032  * they do not make system calls.
00033  *
00034  * WARNING!  This file contains voodoo logic, as black magic is 
00035  * necessary for wrangling with VMS file name.  Woe be to people
00036  * who mess with this code.
00037  *
00038  * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
00039  * 05/03/96 (seiwald) - split from filevms.c
00040  */
00041 
00042 /*
00043  * path_parse() - split a file name into dir/base/suffix/member
00044  */
00045 
00046 void
00047 path_parse( 
00048         char    *file,
00049         PATHNAME *f )
00050 {
00051         char *p, *q;
00052         char *end;
00053         
00054         memset( (char *)f, 0, sizeof( *f ) );
00055 
00056         /* Look for <grist> */
00057 
00058         if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
00059         {
00060             f->f_grist.ptr = file;
00061             f->f_grist.len = p - file;
00062             file = p + 1;
00063         }
00064 
00065         /* Look for dev:[dir] or dev: */
00066 
00067         if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
00068         {
00069             f->f_dir.ptr = file;
00070             f->f_dir.len = p + 1 - file;
00071             file = p + 1;
00072         }
00073 
00074         end = file + strlen( file );
00075 
00076         /* Look for (member) */
00077 
00078         if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
00079         {
00080             f->f_member.ptr = p + 1;
00081             f->f_member.len = end - p - 2;
00082             end = p;
00083         } 
00084 
00085         /* Look for .suffix */
00086         /* This would be memrchr() */
00087 
00088         p = 0;
00089         q = file;
00090 
00091         while( q = (char *)memchr( q, '.', end - q ) )
00092             p = q++;
00093 
00094         if( p )
00095         {
00096             f->f_suffix.ptr = p;
00097             f->f_suffix.len = end - p;
00098             end = p;
00099         }
00100 
00101         /* Leaves base */
00102 
00103         f->f_base.ptr = file;
00104         f->f_base.len = end - file;
00105 
00106         /* Is this a directory without a file spec? */
00107 
00108         f->parent = 0;
00109 }
00110 
00111 /*
00112  *      dir             mods            result
00113  *      ---             ---             ------
00114  * Rerooting:
00115  *
00116  *      (none)          :R=dev:         dev:            
00117  *      devd:           :R=dev:         devd:
00118  *      devd:[dir]      :R=dev:         devd:[dir]
00119  *      [.dir]          :R=dev:         dev:[dir]       questionable
00120  *      [dir]           :R=dev:         dev:[dir]
00121  *
00122  *      (none)          :R=[rdir]       [rdir]          questionable
00123  *      devd:           :R=[rdir]       devd:
00124  *      devd:[dir]      :R=[rdir]       devd:[dir]
00125  *      [.dir]          :R=[rdir]       [rdir.dir]      questionable
00126  *      [dir]           :R=[rdir]       [rdir]
00127  *
00128  *      (none)          :R=dev:[root]   dev:[root]
00129  *      devd:           :R=dev:[root]   devd:
00130  *      devd:[dir]      :R=dev:[root]   devd:[dir]
00131  *      [.dir]          :R=dev:[root]   dev:[root.dir]
00132  *      [dir]           :R=dev:[root]   [dir]
00133  *
00134  * Climbing to parent:
00135  *
00136  */
00137 
00138 # define DIR_EMPTY      0       /* empty string */
00139 # define DIR_DEV        1       /* dev: */
00140 # define DIR_DEVDIR     2       /* dev:[dir] */
00141 # define DIR_DOTDIR     3       /* [.dir] */
00142 # define DIR_DASHDIR    4       /* [-] or [-.dir] */
00143 # define DIR_ABSDIR     5       /* [dir] */
00144 # define DIR_ROOT       6       /* [000000] or dev:[000000] */
00145 
00146 # define G_DIR          0       /* take just dir */
00147 # define G_ROOT         1       /* take just root */
00148 # define G_VAD          2       /* root's dev: + [abs] */
00149 # define G_DRD          3       /* root's dev:[dir] + [.rel] */
00150 # define G_VRD          4       /* root's dev: + [.rel] made [abs] */
00151 # define G_DDD          5       /* root's dev:[dir] + . + [dir] */
00152 
00153 static int grid[7][7] = {
00154 
00155 /* root/dir     EMPTY   DEV     DEVDIR  DOTDIR  DASH,   ABSDIR  ROOT */
00156 /* EMPTY */     G_DIR,  G_DIR,  G_DIR,  G_DIR,  G_DIR,  G_DIR,  G_DIR,
00157 /* DEV */       G_ROOT, G_DIR,  G_DIR,  G_VRD,  G_VAD,  G_VAD,  G_VAD,
00158 /* DEVDIR */    G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_VAD,  G_VAD,  G_VAD,
00159 /* DOTDIR */    G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_DIR,  G_DIR,  G_DIR,
00160 /* DASHDIR */   G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_DDD,  G_DIR,  G_DIR,
00161 /* ABSDIR */    G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_DIR,  G_DIR,  G_DIR,
00162 /* ROOT */      G_ROOT, G_DIR,  G_DIR,  G_VRD,  G_DIR,  G_DIR,  G_DIR,
00163 
00164 } ;
00165 
00166 struct dirinf {
00167         int     flags;
00168 
00169         struct {
00170                 char    *ptr;
00171                 int     len;
00172         } dev, dir;
00173 } ;
00174 
00175 static char *
00176 strnchr( 
00177         char    *buf,
00178         int     c,
00179         int     len )
00180 {
00181         while( len-- )
00182             if( *buf && *buf++ == c )
00183                 return buf - 1;
00184 
00185         return 0;
00186 }
00187 
00188 static void
00189 dir_flags( 
00190         char    *buf,
00191         int     len,
00192         struct dirinf *i )
00193 {
00194         char *p;
00195 
00196         if( !buf || !len )
00197         {
00198             i->flags = DIR_EMPTY;
00199             i->dev.ptr =
00200             i->dir.ptr = 0;
00201             i->dev.len =
00202             i->dir.len = 0;
00203         }
00204         else if( p = strnchr( buf, ':', len ) )
00205         {
00206             i->dev.ptr = buf;
00207             i->dev.len = p + 1 - buf;
00208             i->dir.ptr = buf + i->dev.len;
00209             i->dir.len = len - i->dev.len;
00210             i->flags = i->dir.len && *i->dir.ptr == '[' ? DIR_DEVDIR : DIR_DEV;
00211         }
00212         else
00213         {
00214             i->dev.ptr = buf;
00215             i->dev.len = 0;
00216             i->dir.ptr = buf;
00217             i->dir.len = len;
00218 
00219             if( *buf == '[' && buf[1] == ']' )
00220                 i->flags = DIR_EMPTY;
00221             else if( *buf == '[' && buf[1] == '.' )
00222                 i->flags = DIR_DOTDIR;
00223             else if( *buf == '[' && buf[1] == '-' )
00224                 i->flags = DIR_DASHDIR;
00225             else
00226                 i->flags = DIR_ABSDIR;
00227         }
00228 
00229         /* But if its rooted in any way */
00230 
00231         if( i->dir.len == 8 && !strncmp( i->dir.ptr, "[000000]", 8 ) )
00232             i->flags = DIR_ROOT;
00233 }
00234 
00235 /*
00236  * path_build() - build a filename given dir/base/suffix/member
00237  */
00238 
00239 void
00240 path_build(
00241         PATHNAME *f,
00242         string  *file,
00243         int     binding )
00244 {
00245     struct dirinf root, dir;
00246     int g;
00247 
00248     file_build1( f, file );
00249         
00250     /* Get info on root and dir for combining. */
00251 
00252     dir_flags( f->f_root.ptr, f->f_root.len, &root );
00253     dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
00254 
00255     /* Combine */
00256 
00257     switch( g = grid[ root.flags ][ dir.flags ] )
00258     {
00259     case G_DIR: 
00260         /* take dir */
00261         string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len  );
00262         break;
00263 
00264     case G_ROOT:        
00265         /* take root */
00266         string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
00267         break;
00268 
00269     case G_VAD: 
00270         /* root's dev + abs directory */
00271         string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len  );
00272         string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len  );
00273         break;
00274                 
00275     case G_DRD: 
00276     case G_DDD:
00277         /* root's dev:[dir] + rel directory */
00278         string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
00279 
00280         /* sanity checks: root ends with ] */
00281 
00282         if( file->value[file->size - 1] == ']' )
00283             string_pop_back( file );
00284 
00285         /* Add . if separating two -'s */
00286 
00287         if( g == G_DDD )
00288             string_push_back( file, '.' );
00289 
00290         /* skip [ of dir */
00291         string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1  );
00292         break;
00293 
00294     case G_VRD: 
00295         /* root's dev + rel directory made abs */
00296         string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len  );
00297         string_push_back( file, '[' );
00298         /* skip [. of rel dir */
00299         string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2  );
00300         break;
00301     }
00302 
00303 # ifdef DEBUG
00304     if( DEBUG_SEARCH && ( root.flags || dir.flags ) )
00305     {
00306         printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
00307                 grid[ root.flags ][ dir.flags ], file->value );
00308     }
00309 # endif 
00310 
00311     /* 
00312      * Now do the special :P modifier when no file was present.
00313      *  (none)          (none)
00314      *  [dir1.dir2]     [dir1]
00315      *  [dir]           [000000]
00316      *  [.dir]          (none)
00317      *  []              []
00318      */
00319 
00320     if( file->value[file->size - 1] == ']' && f->parent )
00321     {
00322         char* p = file->value + file->size;
00323         while( p-- > file->value )
00324         {
00325             if( *p == '.' )
00326             {
00327                 /* If we've truncated everything and left with '[',
00328                    return empty string. */
00329                 if (p == file->value + 1)
00330                     string_truncate( file, 0 );
00331                 else {
00332                     string_truncate( file, p - file->value );
00333                     string_push_back( file, ']' );
00334                 }
00335                 break;
00336             }
00337             else if( *p == '-' )
00338             {
00339                 /* handle .- or - */
00340                 if( p > file->value && p[-1] == '.' )
00341                     --p;
00342                 
00343                 *p++ = ']';
00344                 break;
00345             }
00346             else if( *p == '[' )
00347             {
00348                 if( p[1] == ']' )
00349                 {
00350                     /* CONSIDER: I don't see any use of this code. We immediately
00351                        break, and 'p' is a local variable. */
00352                     p += 2;
00353                 }
00354                 else
00355                 {
00356                     string_truncate( file, p - file->value );
00357                     string_append( file, "[000000]" );
00358                 }
00359                 break;
00360             }
00361         }
00362     }
00363 
00364     /* Now copy the file pieces. */
00365 
00366     if( f->f_base.len )
00367     {
00368         string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len  );
00369     }
00370 
00371     /* If there is no suffix, we append a "." onto all generated */
00372     /* names.  This keeps VMS from appending its own (wrong) idea */
00373     /* of what the suffix should be. */
00374 
00375     if( f->f_suffix.len )
00376     {
00377         string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len  );
00378     }
00379     else if( binding && f->f_base.len )
00380     {
00381         string_push_back( file, '.' );
00382     }
00383 
00384     if( f->f_member.len )
00385     {
00386         string_push_back( file, '(' );
00387         string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len  );
00388         string_push_back( file, ')' );
00389     }
00390 
00391 # ifdef DEBUG
00392     if( DEBUG_SEARCH )
00393         printf("built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n", 
00394                f->f_root.len, f->f_root.ptr,
00395                f->f_dir.len, f->f_dir.ptr,
00396                f->f_base.len, f->f_base.ptr,
00397                f->f_suffix.len, f->f_suffix.ptr,
00398                f->f_member.len, f->f_member.ptr,
00399                file->value );
00400 # endif
00401 }
00402 
00403 /*
00404  *      path_parent() - make a PATHNAME point to its parent dir
00405  */
00406 
00407 void
00408 path_parent( PATHNAME *f )
00409 {
00410         if( f->f_base.len )
00411         {
00412             f->f_base.ptr =
00413             f->f_suffix.ptr =
00414             f->f_member.ptr = "";
00415 
00416             f->f_base.len =
00417             f->f_suffix.len =
00418             f->f_member.len = 0;
00419         }
00420         else
00421         {
00422             f->parent = 1;
00423         }
00424 }
00425 
00426 # endif /* VMS */

Generated on Mon Nov 8 17:07:46 2004 for MPT by  doxygen 1.3.9.1