Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/tools/build/jam_src/pathvms.c @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 9.9 KB
Line 
1/*
2 * Copyright 1993-2002 Christopher Seiwald and Perforce Software, Inc.
3 *
4 * This file is part of Jam - see jam.c for Copyright information.
5 */
6
7/*  This file is ALSO:
8 *  Copyright 2001-2004 David Abrahams.
9 *  Distributed under the Boost Software License, Version 1.0.
10 *  (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
11 */
12
13# include "jam.h"
14# include "pathsys.h"
15
16# ifdef OS_VMS
17
18# define DEBUG
19
20/*
21 * pathvms.c - manipulate file names on VMS
22 *
23 * External routines:
24 *
25 *      path_parse() - split a file name into dir/base/suffix/member
26 *      path_build() - build a filename given dir/base/suffix/member
27 *      path_parent() - make a PATHNAME point to its parent dir
28 *
29 * File_parse() and path_build() just manipuate a string and a structure;
30 * they do not make system calls.
31 *
32 * WARNING!  This file contains voodoo logic, as black magic is
33 * necessary for wrangling with VMS file name.  Woe be to people
34 * who mess with this code.
35 *
36 * 02/09/95 (seiwald) - bungled R=[xxx] - was using directory length!
37 * 05/03/96 (seiwald) - split from filevms.c
38 */
39
40/*
41 * path_parse() - split a file name into dir/base/suffix/member
42 */
43
44void
45path_parse( 
46        char    *file,
47        PATHNAME *f )
48{
49        char *p, *q;
50        char *end;
51       
52        memset( (char *)f, 0, sizeof( *f ) );
53
54        /* Look for <grist> */
55
56        if( file[0] == '<' && ( p = strchr( file, '>' ) ) )
57        {
58            f->f_grist.ptr = file;
59            f->f_grist.len = p - file;
60            file = p + 1;
61        }
62
63        /* Look for dev:[dir] or dev: */
64
65        if( ( p = strchr( file, ']' ) ) || ( p = strchr( file, ':' ) ) )
66        {
67            f->f_dir.ptr = file;
68            f->f_dir.len = p + 1 - file;
69            file = p + 1;
70        }
71
72        end = file + strlen( file );
73
74        /* Look for (member) */
75
76        if( ( p = strchr( file, '(' ) ) && end[-1] == ')' )
77        {
78            f->f_member.ptr = p + 1;
79            f->f_member.len = end - p - 2;
80            end = p;
81        } 
82
83        /* Look for .suffix */
84        /* This would be memrchr() */
85
86        p = 0;
87        q = file;
88
89        while( q = (char *)memchr( q, '.', end - q ) )
90            p = q++;
91
92        if( p )
93        {
94            f->f_suffix.ptr = p;
95            f->f_suffix.len = end - p;
96            end = p;
97        }
98
99        /* Leaves base */
100
101        f->f_base.ptr = file;
102        f->f_base.len = end - file;
103
104        /* Is this a directory without a file spec? */
105
106        f->parent = 0;
107}
108
109/*
110 *      dir             mods            result
111 *      ---             ---             ------
112 * Rerooting:
113 *
114 *      (none)          :R=dev:         dev:           
115 *      devd:           :R=dev:         devd:
116 *      devd:[dir]      :R=dev:         devd:[dir]
117 *      [.dir]          :R=dev:         dev:[dir]       questionable
118 *      [dir]           :R=dev:         dev:[dir]
119 *
120 *      (none)          :R=[rdir]       [rdir]          questionable
121 *      devd:           :R=[rdir]       devd:
122 *      devd:[dir]      :R=[rdir]       devd:[dir]
123 *      [.dir]          :R=[rdir]       [rdir.dir]      questionable
124 *      [dir]           :R=[rdir]       [rdir]
125 *
126 *      (none)          :R=dev:[root]   dev:[root]
127 *      devd:           :R=dev:[root]   devd:
128 *      devd:[dir]      :R=dev:[root]   devd:[dir]
129 *      [.dir]          :R=dev:[root]   dev:[root.dir]
130 *      [dir]           :R=dev:[root]   [dir]
131 *
132 * Climbing to parent:
133 *
134 */
135
136# define DIR_EMPTY      0       /* empty string */
137# define DIR_DEV        1       /* dev: */
138# define DIR_DEVDIR     2       /* dev:[dir] */
139# define DIR_DOTDIR     3       /* [.dir] */
140# define DIR_DASHDIR    4       /* [-] or [-.dir] */
141# define DIR_ABSDIR     5       /* [dir] */
142# define DIR_ROOT       6       /* [000000] or dev:[000000] */
143
144# define G_DIR          0       /* take just dir */
145# define G_ROOT         1       /* take just root */
146# define G_VAD          2       /* root's dev: + [abs] */
147# define G_DRD          3       /* root's dev:[dir] + [.rel] */
148# define G_VRD          4       /* root's dev: + [.rel] made [abs] */
149# define G_DDD          5       /* root's dev:[dir] + . + [dir] */
150
151static int grid[7][7] = {
152
153/* root/dir     EMPTY   DEV     DEVDIR  DOTDIR  DASH,   ABSDIR  ROOT */
154/* EMPTY */     G_DIR,  G_DIR,  G_DIR,  G_DIR,  G_DIR,  G_DIR,  G_DIR,
155/* DEV */       G_ROOT, G_DIR,  G_DIR,  G_VRD,  G_VAD,  G_VAD,  G_VAD,
156/* DEVDIR */    G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_VAD,  G_VAD,  G_VAD,
157/* DOTDIR */    G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_DIR,  G_DIR,  G_DIR,
158/* DASHDIR */   G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_DDD,  G_DIR,  G_DIR,
159/* ABSDIR */    G_ROOT, G_DIR,  G_DIR,  G_DRD,  G_DIR,  G_DIR,  G_DIR,
160/* ROOT */      G_ROOT, G_DIR,  G_DIR,  G_VRD,  G_DIR,  G_DIR,  G_DIR,
161
162} ;
163
164struct dirinf {
165        int     flags;
166
167        struct {
168                char    *ptr;
169                int     len;
170        } dev, dir;
171} ;
172
173static char *
174strnchr( 
175        char    *buf,
176        int     c,
177        int     len )
178{
179        while( len-- )
180            if( *buf && *buf++ == c )
181                return buf - 1;
182
183        return 0;
184}
185
186static void
187dir_flags( 
188        char    *buf,
189        int     len,
190        struct dirinf *i )
191{
192        char *p;
193
194        if( !buf || !len )
195        {
196            i->flags = DIR_EMPTY;
197            i->dev.ptr =
198            i->dir.ptr = 0;
199            i->dev.len =
200            i->dir.len = 0;
201        }
202        else if( p = strnchr( buf, ':', len ) )
203        {
204            i->dev.ptr = buf;
205            i->dev.len = p + 1 - buf;
206            i->dir.ptr = buf + i->dev.len;
207            i->dir.len = len - i->dev.len;
208            i->flags = i->dir.len && *i->dir.ptr == '[' ? DIR_DEVDIR : DIR_DEV;
209        }
210        else
211        {
212            i->dev.ptr = buf;
213            i->dev.len = 0;
214            i->dir.ptr = buf;
215            i->dir.len = len;
216
217            if( *buf == '[' && buf[1] == ']' )
218                i->flags = DIR_EMPTY;
219            else if( *buf == '[' && buf[1] == '.' )
220                i->flags = DIR_DOTDIR;
221            else if( *buf == '[' && buf[1] == '-' )
222                i->flags = DIR_DASHDIR;
223            else
224                i->flags = DIR_ABSDIR;
225        }
226
227        /* But if its rooted in any way */
228
229        if( i->dir.len == 8 && !strncmp( i->dir.ptr, "[000000]", 8 ) )
230            i->flags = DIR_ROOT;
231}
232
233/*
234 * path_build() - build a filename given dir/base/suffix/member
235 */
236
237void
238path_build(
239        PATHNAME *f,
240        string  *file,
241        int     binding )
242{
243    struct dirinf root, dir;
244    int g;
245
246    file_build1( f, file );
247       
248    /* Get info on root and dir for combining. */
249
250    dir_flags( f->f_root.ptr, f->f_root.len, &root );
251    dir_flags( f->f_dir.ptr, f->f_dir.len, &dir );
252
253    /* Combine */
254
255    switch( g = grid[ root.flags ][ dir.flags ] )
256    {
257    case G_DIR: 
258        /* take dir */
259        string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len  );
260        break;
261
262    case G_ROOT:       
263        /* take root */
264        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
265        break;
266
267    case G_VAD: 
268        /* root's dev + abs directory */
269        string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len  );
270        string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len  );
271        break;
272               
273    case G_DRD: 
274    case G_DDD:
275        /* root's dev:[dir] + rel directory */
276        string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len  );
277
278        /* sanity checks: root ends with ] */
279
280        if( file->value[file->size - 1] == ']' )
281            string_pop_back( file );
282
283        /* Add . if separating two -'s */
284
285        if( g == G_DDD )
286            string_push_back( file, '.' );
287
288        /* skip [ of dir */
289        string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1  );
290        break;
291
292    case G_VRD: 
293        /* root's dev + rel directory made abs */
294        string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len  );
295        string_push_back( file, '[' );
296        /* skip [. of rel dir */
297        string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2  );
298        break;
299    }
300
301# ifdef DEBUG
302    if( DEBUG_SEARCH && ( root.flags || dir.flags ) )
303    {
304        printf( "%d x %d = %d (%s)\n", root.flags, dir.flags,
305                grid[ root.flags ][ dir.flags ], file->value );
306    }
307# endif
308
309    /*
310     * Now do the special :P modifier when no file was present.
311     *  (none)          (none)
312     *  [dir1.dir2]     [dir1]
313     *  [dir]           [000000]
314     *  [.dir]          (none)
315     *  []              []
316     */
317
318    if( file->value[file->size - 1] == ']' && f->parent )
319    {
320        char* p = file->value + file->size;
321        while( p-- > file->value )
322        {
323            if( *p == '.' )
324            {
325                /* If we've truncated everything and left with '[',
326                   return empty string. */
327                if (p == file->value + 1)
328                    string_truncate( file, 0 );
329                else {
330                    string_truncate( file, p - file->value );
331                    string_push_back( file, ']' );
332                }
333                break;
334            }
335            else if( *p == '-' )
336            {
337                /* handle .- or - */
338                if( p > file->value && p[-1] == '.' )
339                    --p;
340               
341                *p++ = ']';
342                break;
343            }
344            else if( *p == '[' )
345            {
346                if( p[1] == ']' )
347                {
348                    /* CONSIDER: I don't see any use of this code. We immediately
349                       break, and 'p' is a local variable. */
350                    p += 2;
351                }
352                else
353                {
354                    string_truncate( file, p - file->value );
355                    string_append( file, "[000000]" );
356                }
357                break;
358            }
359        }
360    }
361
362    /* Now copy the file pieces. */
363
364    if( f->f_base.len )
365    {
366        string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len  );
367    }
368
369    /* If there is no suffix, we append a "." onto all generated */
370    /* names.  This keeps VMS from appending its own (wrong) idea */
371    /* of what the suffix should be. */
372
373    if( f->f_suffix.len )
374    {
375        string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len  );
376    }
377    else if( binding && f->f_base.len )
378    {
379        string_push_back( file, '.' );
380    }
381
382    if( f->f_member.len )
383    {
384        string_push_back( file, '(' );
385        string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len  );
386        string_push_back( file, ')' );
387    }
388
389# ifdef DEBUG
390    if( DEBUG_SEARCH )
391        printf("built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n", 
392               f->f_root.len, f->f_root.ptr,
393               f->f_dir.len, f->f_dir.ptr,
394               f->f_base.len, f->f_base.ptr,
395               f->f_suffix.len, f->f_suffix.ptr,
396               f->f_member.len, f->f_member.ptr,
397               file->value );
398# endif
399}
400
401/*
402 *      path_parent() - make a PATHNAME point to its parent dir
403 */
404
405void
406path_parent( PATHNAME *f )
407{
408        if( f->f_base.len )
409        {
410            f->f_base.ptr =
411            f->f_suffix.ptr =
412            f->f_member.ptr = "";
413
414            f->f_base.len =
415            f->f_suffix.len =
416            f->f_member.len = 0;
417        }
418        else
419        {
420            f->parent = 1;
421        }
422}
423
424# endif /* VMS */
Note: See TracBrowser for help on using the repository browser.