/* @(#)osfparse.c 17.1.1.1 (ES0-DMD) 01/25/02 17:35:08 */ /*=========================================================================== 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 Unix Version .CATEGORY Host operating system interfaces. File management. .COMMENTS File name Parsing. A file name can be decomposed into path, filename, extension and version. VMS, Unix or MSDOS file naming conventions are recognized. \begin{TeX} In particular, the VMS convention of the colon ({\bf:}) representing a path is accepted, even with multiple pathnames. The following example shows how the translation works with osftr: Let's assume that the environment variable {\em myPath} is defined as \fbox{{\tt .,\$home,/tmp}}. The file named {\tt myPath:test.log} will be looked for, first in the current directory ({\tt .}), if not found in the {\tt \$home} directory, and if still not found in the {\tt /tmp} directory. \end{TeX} .VERSION 1.0 05-Feb-1988 F. Ochsenbein. .VERSION 1.1 05-Apr-1989 Don't convert to uppercase in Unix... .VERSION 1.2 19-Jun-1989 Convention of Logical Names followed by : (to convert names from VMS) .VERSION 1.3 05-Dec-1989 Names followed by : may have several paths, separated by commas. .VERSION 1.4 31-Jan-1990 Removed bug in osfsupply - Cosmetics .VERSION 1.5 23-Nov-1990 Don't crash if NULL filename -----------------------------------------------*/ #include /* ANSI-C prototyping */ #include #include #include #include #include #ifndef F_OK #define F_OK 0 #endif #define COMPONENTS (__PATH_+1) static short int comp1[COMPONENTS][2] = { {0,0}}; static short int comp2[COMPONENTS][2] = { {0,0}}; static char *buffer = NULL_PTR(char); static int lbuffer = 0; /* Index + length of components */ char *osmmget(), *osmmexp(); /*===========================================================================*/ #ifdef __STDC__ static void strlower (char * str ) #else static void strlower ( str ) /*+++++++++ .PURPOSE Converts (in place) a string to lower case .RETURNS Nothing --------*/ char *str; /* MOD: starting address */ #endif { register char *p; for (p = str; *p; p++) *p = tolower(*p); } /*==========================================================================*/ #ifdef __STDC__ static int split(char * name , short comp[6][2]) #else static int split(name, comp) /*+++ .PURPOSE Split a file name into components, returned in `comp'. .RETURNS 0 (Unix) / 1 (VMS or MSDOS) .REMARKS ---*/ char *name; /* IN: EOS-terminated File Name */ short int comp[COMPONENTS][2]; /* OUT: Index + length of components*/ #endif { 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, '/'); /* Unix--like */ if (i < 0) i = oscbloc(name, len, '\\'); /* Look MSDOS */ if (i < 0) i = oscbloc(name, len, ']') ; /* Look VMS */ 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); if ( (status == ']') || (status == '\\') ) status = 1; else status = 0; 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); } /*==========================================================================*/ #ifdef __STDC__ static char * path(char * name , int len) #else static char *path(name, len) /*+++ .PURPOSE Convert a non-Unix (i.e. VMS or MSDOS) pathname .RETURNS Pointer to EOS-terminated pathname if transformation needed .REMARKS Unix-like $... are converted. ---*/ char *name; /* IN: Path Name */ int len; /* IN: Length of Path Name */ #endif { char *p, *pe, *q, savec, dir_sep; char *oshenv(); int i; char the_path[256]; static char zero = EOS; static char *pathname = NULL_PTR(char); static int lpathname = 0; if (len <= 0) return(&zero); pe = name + len - 1; /* Last character */ dir_sep = *pe; if ((dir_sep == '/') && (*name != '$')) return(name); /* No translation required */ i = 0; /* Index in the_path */ if (*name == '$') { q = name + oscloc(name, len, dir_sep); savec = *q, *q = EOS; if (p = oshenv(name+1, NULL_PTR(char))) { while ( (*p) && (i < sizeof(the_path)-1)) the_path[i++] = *(p++); name = q; } *q = savec; } for (p = name; (p <= pe) && (i < sizeof(the_path)-1); ) the_path[i++] = *(p++); the_path[i] = EOS; /* The local variable the_path now contains the path name. Compute length, and Change it if source is MSDOS or VMS */ if (dir_sep == ']') for (p = the_path; *p; p++) if (*p == '-') i += 2; /* VMS - must translate to ../ */ if (i > lpathname) /* Expand Buffer */ lpathname = (i+63)& ~63, pathname = osmmexp(pathname, lpathname); /* Copy with modifications */ p = the_path, q = pathname; if (dir_sep == ']') for( ; *p ; p++) switch(*p) { case '[': savec = 1; /* The next dash has a special meaning */ if (*(++p) == '.') continue; if (*(p--) != '-') *(q++) = '/'; continue; case ']': savec = 1; /* The next dash has a special meaning */ *(q++) = '/'; continue; case '-': if (savec) { savec = 0; /* The next dash is standard */ *(q++) = '.', *(q++) = '.'; continue; } default: savec = 0; /* The next dash is standard */ *(q++) = *p; continue; case '.': savec = 1; /* The next dash has a special meaning */ *(q++) = '/'; continue; } else for( ; *p ; p++) { *(q++) = (*p == '\\' ? '/' : *p); } *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 extracted item(s). .REMARKS Options are _PATH_, _FILE_, _EXTENSION_, _VERSION_. Filenames are NOT converted (use osftr or osfsupply) ---*/ char *name; /* IN: File name */ unsigned int option; /* IN: what to extract, as a \ combination of options */ { char *p; int i, l; 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 */ /* Compute the required length */ l = 1; /* Take into account the EOS! */ for (i = COMPONENTS; --i>=0; ) if (option & (1< lbuffer) lbuffer = (l+63)& ~63, buffer = osmmexp(buffer, lbuffer); /* Now, copy the required items */ p = buffer; 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 */ if (p) { p = buffer + oscopy(buffer, p, lp); /* Copy PathName */ if(ismult) *(p++) = '/'; } else p = buffer; 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 */ if (ismult && (next_path == ',')) /* Check File Exists */ { if (access(buffer, F_OK) != 0) continue; } break; } if (ismult) *(pname + lpath - 1) = ismult; if(isvms) strlower(buffer); 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); }