/* @(#)osfparse.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:25 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetss Ave, Cambridge, MA 02139, USA. Corresponding concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ .TYPE Module .NAME osfparse.c .LANGUAGE C .AUTHOR IPG-ESO Garching .ENVIRONMENT VAX / VMS Version .CATEGORY Host operating system interfaces. File management. .COMMENTS File name Parsing. A file name can be decomposed into path, filename, extension and version. .VERSION 1.0 05-Feb-1988 F. Ochsenbein. .VERSION 1.1 19-Jun-1989 Convention of Logical Names followed by : (to convert names from Unix) .VERSION 1.2 05-Dec-1989 Take care of .. = up subdirectory in Unix. Several paths are available with logicals, e,g, LOG:file.vers with ASSIGN p1,p2 LOG .VERSION 1.3 31-Jan-1990 Cosmetic .VERSION 1.4 23-Nov-1990 Don't crash if NULL filename -----------------------------------------------*/ #include #include #include #define COMPONENTS (__PATH_+1) static short int comp1[COMPONENTS][2] = { {0,0}}; static short int comp2[COMPONENTS][2] = { {0,0}}; /* Index + length of components */ static char *buffer = NULL_PTR(char); static int lbuffer = 0; char *osmmget(), *osmmexp(); /*===========================================================================*/ static void strupper ( str ) /*+++++++++ .PURPOSE Converts (in place) a string to upper case .RETURNS Nothing --------*/ char *str; /* MOD: starting address */ { register char *p; for (p = str; *p; p++) *p = toupper(*p); } /*==========================================================================*/ static int split(name, comp) /*+++ .PURPOSE Split a file name into components, returned in `comp'. .RETURNS The character that ends up the path (] or : or / or EOS) .REMARKS Only written for VMS... ---*/ char *name; /* IN: EOS-terminated File Name */ short int comp[COMPONENTS][2]; /* OUT: Index + length of components*/ { register int i, len, status; oscfill((char *)comp, sizeof(comp1), 0); /* initialize length and indexes */ len = strlen(name); /* The structure of VMS file names is: NODE::DEVICE:[DIRECTORY]FILE.EXTENSION;VERSION */ /* Look for path name (terminated by / ) */ i = oscbloc(name, len, ']'); /* VMS--like */ if (i < 0) i = oscbloc(name, len, '/') ; /* Look Unix */ if (i < 0) i = oscbloc(name, len, '\\'); /* Look MSDOS */ if (i < 0) i = oscbloc(name, len, ':') ; /* Look VMS */ status = 0; if (i >= 0) /* A Path was found, reset name to remaining chars */ { status = *(name + i); comp[__PATH_][1] = ++i; name += i, len -= i; for (i = __PATH_; --i >= 0; ) /* Set Indexes */ comp[i][0] = comp[__PATH_][1]; } /* Look for version */ i = oscbloc(name, len, ';'); if (i >= 0) /* Version Found */ { comp[__VERSION_][0] += i; /* Offset */ comp[__VERSION_][1] = len - i; len = i; } /* Look for extension */ i = oscbloc(name, len, '.'); if (i >= 0) /* Extension Found */ { comp[__EXTENSION_][0] += i; comp[__EXTENSION_][1] = len - i; len = i; } /* Look for file name (remaining bytes) */ comp[__FILE_][1] = len; return(status); } /*==========================================================================*/ static char *path(name, len) /*+++ .PURPOSE Convert a non-VMS (i.e. Unix or MSDOS) pathname .RETURNS Pointer to EOS-terminated pathname if transformation needed .REMARKS ---*/ char *name; /* IN: Path Name */ int len; /* IN: Length of Path Name */ { char *p, *pe, *q, *start, savec, dir_sep; char *oshenv(); int leq, l; static char zero = EOS; static char *pathname = NULL_PTR(char); /* Returned path */ static int lpathname = 0; if (len <= 0) return(&zero); pe = name + len - 1; /* Last character */ dir_sep = *pe; /* Is / for Unix, \ for MSDOS */ if ((dir_sep == ']') || (dir_sep == ':')) return(name); /* VMS Notation */ /* The path uses, either Unix, or MSDOS notation. dir_sep is '/' (Unix notation) or '\' (MSDOS notation) */ l = len + 4; /* Minimal Size for Translated Path Name */ if (*name == '$') q = name + oscloc(name, len, dir_sep); else q = name + len; if (q <= pe) /* Requires Logical Translation */ { savec = *q; *q = EOS; p = oshenv(name+1, NULL_PTR(char)); *q = savec; leq = (p ? strlen(p) : 0); l = leq + 4 + (pe-q); } else leq = 0, l = len+1; l += 3; if (l > lpathname) /* Expand Buffer */ lpathname = (l+63)& ~63, pathname = osmmexp(pathname, lpathname); /* Copy with modificataions */ if(leq) /* Name comes from a $path (logical translation) */ { oscopy(pathname, p, leq); p = q; start = pathname + leq - 1; /* Last byte of translation */ if (*start != ']') *++start = '[', start++; } else { p = name; start = pathname, *(start++) = '['; if ( *p == dir_sep ) p++; /* It's Root directory */ else *(start++) = '.'; /* It's a subdirectory */ } for (q = start; p <= pe; p++, q++) { if (*p == '.') /* Special Files */ { if (*++p == dir_sep) /* ./ = current direct. */ { --q; continue;} if (*p == '.') /* ../ = up directory */ { *q = '-'; continue; } --p; } *q = ( *p == dir_sep ? '.' : *p) ; } if (*(q-1) == '[') *(q++) = ']'; if (*(q-1) == '.') *(q-1) = ']'; *q = EOS; return(pathname); } /*======================================================================*/ char *osfparse(name, option) /*+++ .PURPOSE Extract from a file name the specified items, copy them to an internal buffer. .RETURNS Address of the item(s) to extract .REMARKS Options are _PATH_, _FILE_, _EXTENSION_, _VERSION_. VMS filenames are converted. ---*/ char *name; /* IN: File name */ unsigned int option; /* IN: what to extract, as a \ combination of options */ { char *p, *pname; /* Pathname */ int i, l, lpath; char local_copy[256]; if (!name) name = ""; /* Take default name... */ if (name == buffer) { /* Copy first... */ l = strlen(name) + 1; l = MIN(l, sizeof(local_copy)); oscopy(local_copy, name, l); name = local_copy; } split(name, comp1); /* Split the filename into its components */ if (option & _PATH_) { p = name + comp1[__PATH_][0]; pname = path(p, comp1[__PATH_][1]); if (p == pname) pname = NULL_PTR(char); /* Was not modified */ else comp1[__PATH_][1] = 0; } else pname = NULL_PTR(char); /* Compute the required length */ lpath = 0; l = 1; /* Take into account the EOS! */ if (pname) lpath = strlen(pname), l += lpath; for (i = __PATH_; --i>=0; ) if (option & (1< lbuffer) lbuffer = (l+63)& ~63, buffer = osmmexp(buffer, lbuffer); /* Now, copy the required items */ p = buffer; if (pname) p += oscopy(p, pname, lpath); for (i=COMPONENTS; --i>=0; ) if (option & (1<=0; ) { if (comp1[i][1]) l += comp1[i][1]; else l += comp2[i][1]; } if (l > lbuffer) lbuffer = (l+63)& ~63, buffer = osmmexp(buffer, lbuffer); /* Now, copy the required items */ p = buffer; if (pname) p += oscopy(p, pname, lpath); for (i = __PATH_; --i>=0; ) { if (comp1[i][1]) p += oscopy(p, name + comp1[i][0], comp1[i][1]); else p += oscopy(p, template + comp2[i][0], comp2[i][1]); } *p = EOS; /* Terminate with EOS */ strupper(buffer); /* Convert to UpperCase */ return(buffer); } /*======================================================================*/ char *osftr(name) /*+++ .PURPOSE Convert filename. .RETURNS The address of the converted filename. ---*/ char *name; /* IN: File name */ { if (name != buffer) osfsupply(name, ""); return(buffer); }