[comp.sys.acorn] Unix to Risc OS filenaming

vanaards%t7@uk.ac.man.cs (01/21/91)

   Recetly I noticed a lot of talk about a routine to convert UNIX 
   filenames to RISC OS filenames, but as of yet no one has come up
   with the goods !
   
   So to start the ball rolling I'll post this rather awful routine
   which does the job. It's written in C and is probably too 
   unintelligible to be ported to any other language. I use it in my
   programs - which I've just posted, and it hasn't failed me yet.
   When compiling, try :
  
   cc c.ufn_rofn -DTEST 
   
   if you want to test it out.

   That's all folks !
   
   Steven van Aardt 

   (If we've any Dutch Users I'd like your opinion of the origins 
    of my surname, it apparently has an Afrikanns background.)
                        
-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.-.
| | | | | | | | | | | |  C U T   B E L O W  | | | | | | | | | | | | | | | | |
'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'-'


/*----------------------------------------------------*
 * Module : c.ufn_rofn
 * Purpose: Convert UNIX filenames to RiscOS filename
 * Author : Steven van Aardt
 *----------------------------------------------------*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FALSE 0
#define TRUE (!FALSE)

#define MAX_FILENAME 10

/*---------------------------- Reverse ------------------------*
 * Purpose:   Reverse the character sequence within a string
 * Arguments: Pointer to string
 * Returns:   Pointer to the same string given as an argument.
 *-------------------------------------------------------------*/
static
char *reverse(char *string)
{
  int hd=0,tl=strlen(string);
  char tmp_c;
  /* reverse the name */
  while (--tl>hd) {                   /* work way back from end of string */
    tmp_c=string[hd];
    string[hd++]=string[tl];
    string[tl]=tmp_c;
  }
  return string;
}

/*---------------------------- isvowel --------------------------------*
 * Purpose:   Determines whether a character is an alphabetical vowel
 * Arguments: character (integer form)
 * Returns:   TRUE if vowel, otherwise FALSE.
 *---------------------------------------------------------------------*/
static
int isvowel(int c)
{
  int vowel=FALSE;
  switch (c) {
    case 'a': case 'A':             /* if c matches with */
    case 'e': case 'E':             /* any of these function */
    case 'i': case 'I':             /* will return TRUE */
    case 'o': case 'O':
    case 'u': case 'U': vowel=TRUE;
  }
  return vowel;
}

/*--------------------  squeeze  ------------------------*
 * Purpose:   remove any space characters from a string
 * Arguments: pointer to string
 * Returns:   pointer to a new string.
 *-------------------------------------------------------*/
static
char *squeeze(char *ptr)
{
   int  i=0,j=0;
   char *nn=NULL;
   /* squeeze in-place */
   for (i=j=0; ptr[i]!='\0';i++) if (ptr[i]!=' ') ptr[j++]=ptr[i];
   /* and copy into a new string */
   nn=calloc(j+2,sizeof(char)); /* allocate enough memory for new string */
   strncpy(nn,ptr,j);
   return nn;
}

/*---------------------------- rm_vowels -----------------------------*
 * Purpose:   removes some vowels from a string thus shortening it
 * Arguments: pointer to string
 * Returns:   pointer to a new string.
 *--------------------------------------------------------------------*/
static
char *rm_vowels(char *word,int maxlen)
{
  char *new_word=NULL;
  if (word) {
    int len=strlen(word);
    char *cpy=calloc(len+1,sizeof(char));
    strcpy(cpy,word);
    if (len>maxlen) { 
      /* remove every 2nd vowel */
      int i;
      len--;  /* leave last letter */
      for (i=1; i<len; i+=2) {
        while ((i<len) && (!isvowel(cpy[i]))) i++; /* skip non-vowels */ 
        if ((i<len) && (isvowel(cpy[i]))) cpy[i]=' '; /* overwrite vowels */
      }
    }
    new_word=squeeze(cpy); 
    free(cpy);
  }
  return new_word;
}

/*-------------------  shorten  ----------------------*
 * Purpose:   Shortens a string to a specified length
 * Arguments: pointer to string
 *            max length of string to be.
 * Returns: Pointer to new string
 *----------------------------------------------------*/
static
char *shorten(char *ptr,int maxlen)
{
  char *new_ptr;
  int l=strlen(ptr);
  if (l>maxlen) {
    /* quick shortening by removing a chunk from the middle */
    int num=l-maxlen; /* number to remove to get length of 10 */
    int i,j=0;
    for (i=(l-num)/2; j<num; j++) ptr[i+j]=' ';
  }
  new_ptr=squeeze(ptr);
  return new_ptr;
}



/*--------------------- ufn_rofn ------------------------*
 * Purpose:   Convert UNIX filename to RISC OS filename 
 * Arguments: pointer to UNIX filename string
 * Returns:   pointer to RISC OS filename
 *-------------------------------------------------------*/
extern
char *ufn_rofn(char *unix_name)
{
  typedef struct l List;         /* structure for constituent parts */
  struct l { char *ptr; struct l *last,*next; };
  int  len;
  char *uname=calloc(strlen(unix_name)+1,sizeof(char)),*rname=NULL,*ptr=NULL;
  List *lptr=NULL,*hdptr=NULL,*tlptr=NULL;
  while ((unix_name) && (*unix_name==' ')) unix_name++;
  if ((unix_name) && (*unix_name)) {
    strcpy(uname,unix_name);
    /* look for root directory '/' at beginning of unix filename */
    if (uname[0]=='/') {
      char *tmp=calloc(2,sizeof(char));
      strcpy(tmp,"$");
      lptr=(List *) malloc(sizeof(List));
      tlptr=lptr;         /* pointer to beginning of list */
      lptr->ptr=tmp;      
      lptr->next=NULL;
      lptr->last=hdptr;
      hdptr=lptr;         /* pointer to end of list */
    }
   /*
    *   Break down the name into its directory components - destroys uname
    */
    ptr=strtok(uname,"/");          /* ignores / if at beginning of list */
    while (ptr) {
      char *tmp=calloc(strlen(ptr)+1,sizeof(char));
      strcpy(tmp,ptr);
      lptr=(List *) malloc(sizeof(List));
      if (!tlptr) tlptr=lptr;      /* make pointer to beginning of list */
      if (hdptr) hdptr->next=lptr; /* link previous element onto this */
      lptr->ptr=tmp;
      lptr->next=NULL;   
      lptr->last=hdptr;  /* reverse chained list */
      hdptr=lptr;
      ptr=strtok(NULL,"/");        /* find next '/' */
    }
    /*
     *  Now go through each component looking for a '.' within each.
     */
    lptr=tlptr;                     /* beginning of list */
    while (lptr) {
      char *dp=NULL;                /* dot position */
      dp=strchr(lptr->ptr,'.');
      if (dp) {
        int len=strlen(lptr->ptr);
        /* 
         * special cases
         */
        /* if only 1 dot then refers to the UNIX csd */
        if (len==1) { 
          char *tmp=calloc(2,sizeof(char));
          strcpy(tmp,"@");
          lptr->ptr=tmp;
        } else {
          if (len==2) { 
            char *tmp=calloc(2,sizeof(char)); 
            strcpy(tmp,"^");
            lptr->ptr=tmp;
          } else {
            /* 
             * General case requires reversing of parts around '.'
             */
            List *dlptr=NULL, *dhdptr=NULL, *dtlptr=NULL,*tmp_next=lptr->next;
            char *dptr=NULL,*cpy=calloc(len+1,sizeof(char));

            strcpy(cpy,lptr->ptr);
            reverse(cpy);           /* reverse complete text */
            dptr=strtok(cpy,".");
            while (dptr) {
              char *tmp=calloc(strlen(dptr)+1,sizeof(char));  
              strcpy(tmp,dptr); /* make a copy of part */ 
              dlptr=(List *) malloc(sizeof(List));
              if (!dtlptr) dtlptr=dlptr;  /* remember beginning of this list */
              if (dhdptr) dhdptr->next=dlptr; /* link previous one onto this */
              dlptr->ptr=reverse(tmp); /* and reverse it's text back again */
              dlptr->next=NULL;
              dlptr->last=dhdptr;  /* reverse chaining  */
              dhdptr=dlptr;
              dptr=strtok(NULL,".");
            } /* endwhile */
            if (lptr->last) {
              free(lptr->ptr);       /* free text worked on by above */
              lptr=lptr->last;       /* move back */
              free(lptr->next);      /* free text's list element */
              lptr->next=dtlptr;     /* link */
              dtlptr->last=lptr;
              dlptr->next=tmp_next;
              if (tmp_next) { 
                tmp_next->last=dlptr;
                lptr=tmp_next->last;
              } else lptr=dlptr;
            } else {        /* case when this is the head of the list */
              free(lptr->ptr);
              free(lptr);
              lptr=dtlptr;
              tlptr=lptr;
              lptr->last=NULL;
              dlptr->next=tmp_next;
              if (tmp_next) {
                tmp_next->last=dlptr;
                lptr=tmp_next->last;
              } else lptr=dlptr;
            } /* endif */
          } /* endif */
        } /* endif */
      } /* endif */ 
      lptr=lptr->next; /* move onto next directory component in list */
    } /* endwhile */
    /* 
     *  Check the lengths of each component and adjust to that for RISC OS
     */
    lptr=tlptr;
    len=0;
    while (lptr) {
      char *new_ptr=NULL;
      if (lptr->next) len+=1;  /* for the RISC OS directory separator */
      new_ptr=rm_vowels(lptr->ptr,MAX_FILENAME);
      free(lptr->ptr);
      lptr->ptr=new_ptr;
      new_ptr=shorten(lptr->ptr,MAX_FILENAME);
      free(lptr->ptr);
      lptr->ptr=new_ptr;
      len+=strlen(lptr->ptr);
      lptr=lptr->next;
    }
    /*
     *  Copy linked list into result string
     */
    rname=calloc(len+1,sizeof(char)); /* make suitable string space */
    lptr=tlptr;
    len=0;
    while (lptr) {
      strcat((rname+len),lptr->ptr);
      free(lptr->ptr);     
      len=strlen(rname);
      lptr=lptr->next;
      if (lptr) strcat(rname,"."); /* append RISC OS directory separator */
    }
    /*
     *  Tidy up, by freeing memory used by list
     */
    lptr=tlptr;
    while (lptr) {
      List *tmp;
      tmp=lptr;
      lptr=lptr->next;
      free(tmp);
    }
  } /* endif */
  free(uname);
  return rname;
}




#ifdef TEST

int main(void) {
  char unix_filename[256],*riscos_filename;

  while (!feof(stdin)) {
     printf("Enter Unix filename : ");
     scanf("%s",&unix_filename);
     if (!feof(stdin)) {
       riscos_filename=ufn_rofn(unix_filename);
       printf("Risc OS filename    : %s\n",riscos_filename);
       free(riscos_filename);
     }
  }
  return 0;
}

#endif

+--------------------------------+-----------------------------------------+
|   ()()TEVEN         ()         |                                         |  
|  ()                ()()        |                                         |  
|   ()()   ()  ()AN ()  ()       |                                         |
|      ()   ()()   ()()()()      +-----------------------------------------+
|   ()()     ()   ()      ()ARDT |JANET E-mail : vanaards@uk.ac.man.cs.p4  |
+--------------------------------+-----------------------------------------+