home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 3 / TheARMClub_PDCD3.iso / hensa / textprocess / grep_2 / release / c / wild < prev   
Text File  |  1998-09-23  |  15KB  |  538 lines

  1. /*->c.wild */
  2.  
  3. /* wildcard code added by David Pilling for the Archimedes */
  4. /* bits taken from C Kermit */
  5.  
  6. /* Section modified by Justin Fletcher to work with kernel.h and swis.h
  7.    rather than arthur.h */
  8.  
  9. #include <stdlib.h>
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include "kernel.h"
  14. #include "swis.h"
  15.  
  16. #define MAXWLD 512                     /* Maximum wildcard filenames */
  17. #define MAXNAMLEN 255
  18.  
  19.  
  20. static int fcount;                     /* Number of files in wild group */
  21. static char nambuf[MAXNAMLEN+2];       /* Buffer for a filename */
  22.  
  23. static char *mtchs[MAXWLD],            /* Matches found for filename */
  24.      **mtchptr;                        /* Pointer to current match */
  25.  
  26.  
  27. /*
  28.  * osgbpb with r0==9 is used to read directory names;
  29.  * the data returned is copied into a struct dirent.
  30.  */
  31.  
  32. struct dirent {
  33.        unsigned int d_reclen;               /* length of this record */
  34.        unsigned int d_namlen;               /* length of string in d_name */
  35.        char    d_name[MAXNAMLEN + 1];  /* name must be no longer than this */
  36. };
  37.  
  38. /*
  39.  * This macro calculates the amount of storage required for
  40.  * the directory entry.
  41.  */
  42. #undef DIRSIZ
  43. #define DIRSIZ(dp) \
  44.     ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &3))
  45.  
  46. /*
  47.  * Definitions for library routines operating on directories.
  48.  */
  49. typedef struct _dirdesc
  50. {
  51.        long    dd_pos; /* current position in directory. */
  52.        struct dirent *dd_dirent;
  53.        char    dd_name[MAXNAMLEN+1]; /* osgbpb needs a name */
  54.        char    dd_buf[MAXNAMLEN+1]; /* osgbpb needs a buffer */
  55. } DIR;
  56.  
  57. extern DIR *opendir( char * );
  58. extern void closedir( DIR *);
  59.  
  60. struct FileData {int loadaddr, execaddr, length, attrib;};
  61.  
  62. struct BTim {int low, high;};
  63.  
  64. int
  65. GetFileInformation(
  66.   struct FileData *info,
  67.   struct BTim *tstamp,
  68.   char * name,
  69.   int len )
  70. {
  71. static _kernel_osfile_block o_b;
  72. static _kernel_swi_regs rs;
  73. _kernel_oserror *ret;
  74. int objtype;
  75.  
  76. #define osfind(regs) _kernel_swi(OS_Find,regs,regs)
  77. #define osfile(regs) _kernel_swi(OS_Find,regs,regs)
  78.  
  79.     /* printf("Info on %s\n",name); */
  80.     /* Open file for reading */
  81.     rs.r[0] = 0x40;
  82.     rs.r[1] = (int)name;
  83.     if( (ret=osfind( &rs )) != NULL )
  84.     {
  85.         fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
  86.         return -1;
  87.     }
  88.  
  89.     if( rs.r[0] == 0 )
  90.         /* File does not exist */
  91.         return -1;
  92.  
  93.     /* close the file just opened */
  94.     rs.r[1] = rs.r[0];
  95.     rs.r[0] = 0;
  96.  
  97.     if( (ret=osfind( &rs )) != NULL )
  98.     {
  99.         fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
  100.         return -1;
  101.     }
  102.  
  103.     /* o_b.action = 5; */
  104.     /* o_b.name = name; */
  105.  
  106.     if( (objtype=_kernel_osfile( 5,name,&o_b )) <0 )
  107.     {
  108.         ret=_kernel_last_oserror();
  109.         fprintf(stderr,"%s (%d)\n",ret->errmess,ret->errnum);
  110.         return -1;
  111.     }
  112.     /* printf("Objtype=%i\n",objtype); */
  113.  
  114.     info->loadaddr = o_b.load;
  115.     info->execaddr = o_b.exec;
  116.     info->length = o_b.start;
  117.     info->attrib = o_b.end;
  118.  
  119.     len=0; /* filename len */
  120.     tstamp->low=0;
  121.  
  122.     /* Return file type */
  123.     return objtype;
  124. }
  125.  
  126. DIR *
  127. opendir( filename )
  128. char *filename;
  129. {
  130. DIR * dirp;
  131.  
  132.         if( (dirp = (DIR*)malloc(sizeof(DIR))) == NULL )
  133.                 return NULL;
  134.  
  135.         if( (dirp->dd_dirent =
  136.                 (struct dirent*)malloc(sizeof(struct dirent))) == NULL )
  137.                 return NULL;
  138.  
  139.         dirp->dd_pos = 0;
  140.         strcpy( dirp->dd_name, filename );
  141.  
  142.         return dirp;
  143.  
  144. }
  145.  
  146. struct dirent *
  147. readdir( dirp )
  148. DIR *dirp;
  149. {
  150. static _kernel_osgbpb_block par;
  151. struct dirent *dp;
  152. char *name;
  153.  
  154.     /* par.action = 9; */
  155.     /* par.file_handle = (int)dirp->dd_name; */
  156.     par.dataptr = dirp->dd_buf;
  157.     par.nbytes = 1;
  158.     par.fileptr = (int)dirp->dd_pos;
  159.     par.buf_len = sizeof( dirp->dd_buf );
  160.     par.wild_fld = "*";
  161.  
  162.     /* printf("Doing GBPB on %s\n",dirp->dd_name); */
  163.     if( _kernel_osgbpb( 9, (int)dirp->dd_name, &par ) ==-2 )
  164.         return NULL;
  165.  
  166.     if( (par.nbytes != 1) || (par.fileptr == -1) )
  167.         return NULL;
  168.  
  169.     name = dirp->dd_buf;
  170.     /* printf("Read %s\n",name); */
  171.  
  172.     dp = dirp->dd_dirent;
  173.  
  174.     dp->d_namlen = strlen( name );
  175.     dp->d_reclen = sizeof(struct dirent) - (MAXNAMLEN+1) +
  176.                                                   dp->d_namlen + 1;
  177.     strcpy( dp->d_name, name );
  178.  
  179.     dirp->dd_pos++;
  180.  
  181.     return dp;
  182.  
  183. }
  184.  
  185. long
  186. telldir( dirp )
  187. DIR *dirp;
  188. {
  189.         return dirp->dd_pos;
  190. }
  191.  
  192. void
  193. seekdir( dirp, loc )
  194. DIR *dirp;
  195. long loc;
  196. {
  197.         dirp->dd_pos = loc;
  198.         return;
  199. }
  200.  
  201. void
  202. closedir( dirp )
  203. DIR *dirp;
  204. {
  205.         free( dirp->dd_dirent );
  206.         free( dirp );
  207.         return;
  208. }
  209.  
  210.  
  211. /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
  212.  
  213. /*
  214.  * The path structure is used to represent the name to match.
  215.  * Each slash-separated segment of the name is kept in one
  216.  * such structure, and they are linked together, to make
  217.  * traversing the name easier.
  218.  */
  219.  
  220. struct path {
  221.               char npart[MAXNAMLEN];   /* name part of path segment */
  222.               struct path *fwd;                /* forward ptr */
  223.             };
  224.  
  225.  
  226. #define SSPACE 2000                     /* size of string-generating buffer */
  227. static char sspace[SSPACE];             /* buffer to generate names in */
  228. static char *freeptr,**resptr;          /* copies of caller's arguments */
  229. static int remlen;                      /* remaining length in caller's array*/
  230. static int numfnd;                      /* number of matches found */
  231.  
  232. void traverse(struct path *,char *,char *);
  233. int  match(char *,char *);
  234. void addresult(char *);
  235. int  iswild(char *);
  236.  
  237. /*
  238.  * splitpath:
  239.  *  takes a string and splits the slash-separated portions into
  240.  *  a list of path structures.  Returns the head of the list.  The
  241.  *  structures are allocated by malloc, so they must be freed.
  242.  *  Splitpath is used internally by the filename generator.
  243.  *
  244.  * Input: A string.
  245.  * Returns: A linked list of the slash-separated segments of the input.
  246.  */
  247.  
  248. struct path * splitpath(p) char *p;
  249. {
  250.  struct path *head,*cur,*prv;
  251.  int i;
  252.  head = prv = NULL;
  253.  
  254.  if (*p == ':') p+=2;
  255.  if (*p==  '.') p++;
  256.  
  257.  while (*p != '\0')
  258.  {
  259.    cur = (struct path *) malloc(sizeof (struct path));
  260.    if (cur == NULL) {fprintf(stderr,"malloc fails in splitpath()\n");exit(1);}
  261.    cur -> fwd = NULL;
  262.    if (head == NULL) head = cur;
  263.    else prv -> fwd = cur;       /* link into chain */
  264.    prv = cur;
  265.  
  266.    for (i=0; i < MAXNAMLEN && *p != '.' && *p != '\0'; i++)
  267.      cur -> npart[i] = *p++;
  268.    cur -> npart[i] = '\0';      /* end this segment */
  269.    if (i >= MAXNAMLEN) while (*p != '.' && *p != '\0') p++;
  270.    if (*p == '.') p++;
  271.  }
  272.  
  273.  return(head);
  274. }
  275.  
  276.  
  277. /*
  278.  * fgen:
  279.  *  This is the actual name generator.  It is passed a string,
  280.  *  possibly containing wildcards, and an array of character pointers.
  281.  *  It finds all the matching filenames and stores them into the array.
  282.  *  The returned strings are allocated from a static buffer local to
  283.  *  this module (so the caller doesn't have to worry about deallocating
  284.  *  them); this means that successive calls to fgen will wipe out
  285.  *  the results of previous calls.  This isn't a problem here
  286.  *  because we process one wildcard string at a time.
  287.  *
  288.  * Input: a wildcard string, an array to write names to, the
  289.  *        length of the array.
  290.  * Returns: the number of matches.  The array is filled with filenames
  291.  *          that matched the pattern.  If there wasn't enough room in the
  292.  *         array, -1 is returned.
  293.  * By: Jeff Damens, CUCCA, 1984.
  294.  */
  295.  
  296. int fgen(pat,resarry,len)
  297. char *pat,*resarry[];
  298. int len;
  299. {
  300.  struct path *head;
  301.  char scratch[100],*sptr;
  302.  
  303.  head = splitpath(pat);
  304.  if (*pat != ':')
  305.  {
  306.   scratch[0] = '\0';
  307.   sptr = scratch;
  308.  }
  309.  else
  310.  {
  311.   strcpy(scratch,pat);
  312.   scratch[3]=0;
  313.   sptr = scratch+3;
  314.  }
  315.                                      /* init buffer correctly */
  316.  numfnd = 0;                           /* none found yet */
  317.  freeptr = sspace;                     /* this is where matches are copied */
  318.  resptr = resarry;                     /* static copies of these so*/
  319.  remlen = len;                         /* recursive calls can alter them */
  320.  traverse(head,scratch,sptr);          /* go walk the directory tree */
  321.  for (; head != NULL; head = head -> fwd)
  322.    free(head);                         /* return the path segments */
  323.  return(numfnd);                       /* and return the number of matches */
  324. }
  325.  
  326. /* traverse:
  327.  *  Walks the directory tree looking for matches to its arguments.
  328.  *  The algorithm is, briefly:
  329.  *   If the current pattern segment contains no wildcards, that
  330.  *   segment is added to what we already have.  If the name so far
  331.  *   exists, we call ourselves recursively with the next segment
  332.  *   in the pattern string; otherwise, we just return.
  333.  *
  334.  *   If the current pattern segment contains wildcards, we open the name
  335.  *   we've accumulated so far (assuming it is really a directory), then read
  336.  *   each filename in it, and, if it matches the wildcard pattern segment, add
  337.  *   that filename to what we have so far and call ourselves recursively on the
  338.  *   next segment.
  339.  *
  340.  *   Finally, when no more pattern segments remain, we add what's accumulated
  341.  *   so far to the result array and increment the number of matches.
  342.  *
  343.  * Input: a pattern path list (as generated by splitpath), a string
  344.  *       pointer that points to what we've traversed so far (this
  345.  *       can be initialized to "/" to start the search at the root
  346.  *       directory, or to "./" to start the search at the current
  347.  *       directory), and a string pointer to the end of the string
  348.  *       in the previous argument.
  349.  * Returns: nothing.
  350.  */
  351.  
  352.  
  353. void
  354. traverse(pl,sofar,endcur)
  355. struct path *pl;
  356. char *sofar,*endcur;
  357. {
  358.  DIR *fd;
  359.  struct dirent dir_entry;
  360.  struct dirent *dirbuf = &dir_entry;
  361.  
  362.  struct FileData fileinfo;
  363.  struct BTim timeinfo;
  364.  int rc;
  365.  int stamped;
  366.  
  367.  if (pl == NULL)
  368.  {
  369.   *--endcur = '\0';                    /* end string, overwrite trailing / */
  370.   addresult(sofar);
  371.   return;
  372.  }
  373.  
  374.  if (!iswild(pl -> npart))
  375.  {
  376.   strcpy(endcur,pl -> npart);
  377.   endcur += strlen(pl -> npart);
  378.   *endcur = '\0';                      /* end current string */
  379. /*  if (stat(sofar,&statbuf) == 0) */      /* if current piece exists */
  380.   rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
  381.   if( rc >= 0 )  /* if current piece exists */
  382.   {
  383.       *endcur++ = '.';                  /* add slash to end */
  384.       *endcur = '\0';                  /* and end the string */
  385.       traverse(pl -> fwd,sofar,endcur);
  386.   }
  387.   return;
  388.  }
  389.  
  390. /* segment contains wildcards, have to search directory */
  391.  
  392.  *endcur = '\0'; /* end current string */
  393.  if( *(endcur-1) == '.' )
  394.  {
  395.    /* Stamp on trailing . */
  396.    *--endcur = '\0';
  397.    stamped = 1;
  398.  }
  399.  else
  400.    stamped = 0;
  401. /* if (stat(sofar,&statbuf) == -1) return;*/   /* doesn't exist, forget it */
  402. /* if ((statbuf.st_mode & S_IFDIR) == 0) return;*/  /* not a directory, skip */
  403.  
  404.  if( sofar[0] != '\0' )
  405.  {
  406.   /* cwd is represented as a NULL string!! */
  407.   rc = GetFileInformation(&fileinfo, &timeinfo, sofar, strlen(sofar));
  408.   if( rc == -1 ) return;   /* doesn't exist, forget it */
  409.   if( rc != 2 ) return;    /* not a directory, skip */
  410.  }
  411.  
  412.  if ((fd = opendir(sofar)) == NULL) return;    /* can't open, forget it */
  413.  
  414.  if( stamped != 0 )
  415.  {
  416.    *endcur++ = '.';
  417.    *endcur = '\0';
  418.  }
  419.  
  420.  while ( (dirbuf = readdir(fd)) != NULL )
  421.  {
  422.   strncpy(nambuf,dirbuf->d_name,MAXNAMLEN); /* Get a null terminated copy!!! */
  423.   nambuf[MAXNAMLEN] = '\0';
  424. /*  if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) {*/
  425.   if ( match(pl -> npart,nambuf)) {
  426.     char *eos;
  427.     strcpy(endcur,nambuf);
  428.     eos = endcur + strlen(nambuf);
  429.     *eos = '.';                    /* end this segment */
  430.     traverse(pl -> fwd,sofar,eos+1);
  431.  }
  432. }
  433.  
  434.  closedir(fd);
  435. }
  436. /*
  437.  * addresult:
  438.  *  Adds a result string to the result array.  Increments the number
  439.  *  of matches found, copies the found string into our string
  440.  *  buffer, and puts a pointer to the buffer into the caller's result
  441.  *  array.  Our free buffer pointer is updated.  If there is no
  442.  *  more room in the caller's array, the number of matches is set to -1.
  443.  * Input: a result string.
  444.  * Returns: nothing.
  445.  */
  446.  
  447. void addresult(str)
  448. char *str;
  449. {
  450.  int l;
  451.  if (strncmp(str,"./",2) == 0) str += 2;
  452.  if (--remlen < 0) {
  453.   numfnd = -1;
  454.   return;
  455.  }
  456.  l = strlen(str) + 1;                  /* size this will take up */
  457.  if ((freeptr + l) > &sspace[SSPACE-1]) {
  458.     numfnd = -1;                       /* do not record if not enough space */
  459.     return;
  460.   }
  461.  strcpy(freeptr,str);
  462.  *resptr++ = freeptr;
  463.  freeptr += l;
  464.  numfnd++;
  465. }
  466.  
  467.  
  468. int iswild(str)
  469. char *str;
  470. {
  471.  char c;
  472.  while ((c = *str++) != '\0')
  473.    if (c == '*' || c == '?') return(1);
  474.  return(0);
  475. }
  476.  
  477. /*
  478.  * match:
  479.  *  pattern matcher.  Takes a string and a pattern possibly containing
  480.  *  the wildcard characters '*' and '?'.  Returns true if the pattern
  481.  *  matches the string, false otherwise.
  482.  * by: Jeff Damens, CUCCA
  483.  *
  484.  * Input: a string and a wildcard pattern.
  485.  * Returns: 1 if match, 0 if no match.
  486.  */
  487.  
  488. int match(pattern,string) char *pattern,*string; {
  489.     char *psave,*ssave;           /* back up pointers for failure */
  490.     psave = ssave = NULL;
  491.     while (1) {
  492.        for (; toupper(*pattern)==toupper(*string); pattern++,string++)
  493.                                                /* skip first */
  494.            if (*string == '\0') return(1);     /* end of strings, succeed */
  495.        if (*string != '\0' && *pattern == '?') {
  496.            pattern++;                  /* '?', let it match */
  497.            string++;
  498.        } else if (*pattern == '*') {   /* '*' ... */
  499.            psave = ++pattern;          /* remember where we saw it */
  500.            ssave = string;             /* let it match 0 chars */
  501.        } else if (ssave != NULL && *ssave != '\0') {   /* if not at end  */
  502.                                        /* ...have seen a star */
  503.            string = ++ssave;           /* skip 1 char from string */
  504.            pattern = psave;            /* and back up pattern */
  505.        } else return(0);               /* otherwise just fail */
  506.     }
  507. }
  508.  
  509.  
  510.  
  511. /*  Z X P A N D  --  Expand a wildcard string into an array of strings  */
  512. /*
  513.   Returns the number of files that match fn1, with data structures set up
  514.   so that first file (if any) will be returned by the next znext() call.
  515. */
  516. int zxpand(fn) char *fn;
  517. {
  518.   fcount = fgen(fn,mtchs,MAXWLD);    /* Look up the file. */
  519.   if (fcount > 0)
  520.   {
  521.      mtchptr = mtchs;                /* Save pointer for next. */
  522.   }
  523.   return(fcount);
  524. }
  525.  
  526.  
  527. /*  Z N E X T  --  Get name of next file from list created by zxpand(). */
  528. /*
  529.  Returns >0 if there's another file, with its name copied into the arg string,
  530.  or 0 if no more files in list.
  531. */
  532. int znext(fn) char *fn; {
  533.     if (fcount-- > 0) strcpy(fn,*mtchptr++);
  534.     else *fn = '\0';
  535.     return(fcount+1);
  536. }
  537.  
  538.