/******************************************************************************** ** COPYRIGHT (c) 1998 BY * ** COMPAQ COMPUTER CORPORATION * ** ALL RIGHTS RESERVED. * ** * ** Permission is granted to use or copy any part of this example program * ** with the inclusion of the above copyright notice. * ** * *********************************************************************************/ #define __NEW_STARLET #include #include #include #include #include #include #include typedef int BOOL; // Note: Set your screen to 132 columns wide to read this program // // This module contains a routine, UpcaseFilename, which can be used to convert filenames // into a standardized, all-upper-case form. It also includes a main program to show you // how to use the routine to compare two different filenames to determine if they are // functionally identical. Each routine is described more thoroughly in comments at its // beginning. // // To build this module so you can run the test program, compile it and link it in // the normal manner, i.e.: // // $CC FILENAME_COMPARE // $LINK FILENAME_COMPARE int UpcaseFilename(struct dsc$descriptor_s *inputFilespec,BOOL noDelimiters, struct dsc$descriptor_s *outputFilespec,unsigned short int *outLength) { // This routine's purpose is to take a filename (that is, the name.type;version part of a filespec) and to turn it // into an upper case version in canonical form. This form allows it to be compared with another filename that has // has been similarly treated. // // The input and output strings (inputFilespec and outputFilespec) must be the addresses of fixed length string // descriptors. The routine returns the length of the output filename in the short integer (word) outLength. // // You can also optionally tell the routine to ignore name/type/version delimiters by setting "noDelimiters" to a // non-zero value. In this case, it will not add delimiters, and it will not treat the last ; and period as a // version or type delimiter. // int status; unsigned short int length; unsigned int inFlags=0,outFlags; char QIOFileSpec[538]; struct dsc$descriptor_s QIOFileSpecDesc = {538,DSC$K_DTYPE_T,DSC$K_CLASS_S,QIOFileSpec}; if (noDelimiters) { // If the caller asked for no delimiters, tell the convert system service the same // thing. inFlags = CVTFNM$M_NO_DELIMITERS; } // First convert the specified filename into its ACPQIO form. The main reason we do this // is because what we really want is the upcase and the canonical form which the inverse // conversion gives us. We could have done this with $PARSE except that if we use a NAM, // we get DIDing and FIDding, and if we use a NAML, we do not get upcasing. status = SYS$CVT_FILENAME(CVTFNM$C_RMS_TO_ACPQIO,inputFilespec,inFlags, &QIOFileSpecDesc,&length,&outFlags); // Set the descriptor for the ACPQIO version to the actual length of the string QIOFileSpecDesc.dsc$w_length = length; #ifdef DEBUG if (outFlags & CVTFNM$M_WORD_CHARS) { //We don't have the right equipment to print out a 2-byte string, so just give info printf("QIO Filespec has two-byte characters. Status = %d, string length (bytes) = %d\n", status,length); } else { // Zero-terminate the string and print it out for debugging QIOFileSpec[QIOFileSpecDesc.dsc$w_length] = 0; printf ("QIO Filespec: Status = %d, string = %s\n",status,QIOFileSpec); } #endif if (!(status && 1)) return status; // Set the input flags to upcase the result, and tell the conversion whether // the ACPQIO string we are giving it has 2-byte characters or not. // InFlags will still have the nodelimiters flag if we set it earlier. inFlags |= CVTFNM$M_FORCE_UPCASE; if (outFlags & CVTFNM$M_WORD_CHARS) inFlags |= CVTFNM$M_WORD_CHARS; status = SYS$CVT_FILENAME(CVTFNM$C_ACPQIO_TO_RMS,&QIOFileSpecDesc,inFlags, outputFilespec,outLength,&outFlags); return status; } // // This is a demo of the UpcaseFilename routine at the beginning of this file. It also // demonstrates how to use the routine to compare two filenames for equality. To use this // routine, you must use the VMS "foreign command" syntax. You can do this either by defining // a symbol to point to the image, or by using the DCL$PATH logical. For example; // // either $DEFINE DCL$PATH DKA100:[Upcase] // or $Upcase == "$DKA100:[Upcase]UPCASE.EXE" // // will allow you to start this routine a command like // // $ Upcase -file aaa^;bbb.txt -file AAA^;bbb.TxT // // The result of this command should be that you see both files printed in upper case and a line // stating that the two files are the same. // int main(int argc, char *argv[], char *envp[]) { char RMSFileSpec[2][NAML$C_MAXRSS]; char RMSFileSpecOut[2][NAML$C_MAXRSS]; struct dsc$descriptor_s RMSFileSpecDesc[2] = {NAML$C_MAXRSS,DSC$K_DTYPE_T,DSC$K_CLASS_S,RMSFileSpec[0], NAML$C_MAXRSS,DSC$K_DTYPE_T,DSC$K_CLASS_S,RMSFileSpec[1]}; struct dsc$descriptor_s RMSFileSpecOutDesc[2] = {NAML$C_MAXRSS,DSC$K_DTYPE_T,DSC$K_CLASS_S,RMSFileSpecOut[0], NAML$C_MAXRSS,DSC$K_DTYPE_T,DSC$K_CLASS_S,RMSFileSpecOut[1]}; BOOL doCompare=TRUE, noDelimiters=FALSE; int i,numberOfFiles=0; RMSFileSpec[0][0] = 0; RMSFileSpec[1][0] = 0; /* Parse the arguments */ for (i=1; i < argc; i++) /*argv[0] is the image path*/ { if (strcmp(argv[i],"-file") == 0) { i++; if (i>= argc) break; if (numberOfFiles < 2) { strncpy(RMSFileSpec[numberOfFiles],argv[i],NAML$C_MAXRSS); RMSFileSpecDesc[numberOfFiles].dsc$w_length = strlen(RMSFileSpec[numberOfFiles++]); } else printf("Too many filespecs. The first two are used.\n"); } else if (strcmp(argv[i],"-delimiters") == 0) { noDelimiters = FALSE; } else if (strcmp(argv[i],"-nodelimiters") == 0) { noDelimiters = TRUE; } else { if (strcmp(argv[i],"?") != 0) { printf ("Unknown argument %s\n",argv[i]); } else { printf("This program demonstrates using the $CVTFNM system service to do upcasing\n"); printf("and filename comparisons.\n"); printf ("\n"); } printf ("\nUsage:\n"); printf ("? Print this message including general informative info\n"); printf ("\n"); printf ("-file string Specify one of the filenames to operate on (you can specify up to 2)\n"); printf ("\n"); printf ("Negatable options (with 'no')\n"); printf ("\n"); printf ("-delimiters The filespecs you entered have type and version delimiters\n"); return 0; } } if (numberOfFiles == 0) { printf ("No filespecs specified. Exiting...\n"); return 0; } if (numberOfFiles == 1) { doCompare = FALSE; } for (i=0; i < numberOfFiles; i++) { int status; unsigned short int length; status = UpcaseFilename(&RMSFileSpecDesc[i],noDelimiters,&RMSFileSpecOutDesc[i],&length); RMSFileSpecOut[i][length] = 0; printf ("RMS Filespec %d: Status = %d, string = %s\n",i,status,RMSFileSpecOut[i]); } if (doCompare) { if (strcmp(RMSFileSpecOut[0],RMSFileSpecOut[1]) == 0) printf("Filenames match\n"); else printf("Filenames do not match\n"); } return 0; }