home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / editor / elvis / sources / amiwild.c < prev    next >
C/C++ Source or Header  |  1994-01-30  |  6KB  |  294 lines

  1. /* amiwild.c */
  2.  
  3. /*-
  4.  *    Mike Rieser                 Dale Rahn
  5.  *    2410 Happy Hollow Rd. Apt D-10        540 Vine St.
  6.  *    West Lafayette, IN 47906         West Lafayette, IN 47906
  7.  *    riesermc@mentor.cc.purdue.edu        rahn@sage.cc.purdue.edu
  8.  */
  9.  
  10. /* #include <string.h> */
  11. #include <stdio.h>
  12. #include <stddef.h>
  13. #include <exec/memory.h>
  14. #include <dos/dosextens.h>
  15. #include <clib/dos_protos.h>
  16.  
  17. /* Some needed prototypes from clib/exec_protos.h */
  18. extern APTR  AllocMem(unsigned long byteSize, unsigned long requirements);
  19. extern void  FreeMem(APTR memoryBlock, unsigned long byteSize);
  20. extern struct Library *OpenLibrary(UBYTE * libName, unsigned long version);
  21. extern void  CloseLibrary(struct Library *library);
  22.  
  23. #if AZTEC_C
  24. #include <pragmas/exec_lib.h>
  25. #include <pragmas/dos_lib.h>
  26. #else
  27. #include <pragmas/exec.h>
  28. #include <pragmas/dos.h>
  29. #endif
  30.  
  31. #define    DOS_LIBRARY    ((UBYTE *) "dos.library")
  32.  
  33. #ifdef AZTEC_C
  34. /* Some needed prototypes from string.h and stdlib.h */
  35. extern char *strdup(char *);
  36. extern char *strpbrk(char *, char *);
  37. extern void *realloc(void *, size_t);
  38. extern void  free(void *);
  39. #endif
  40.  
  41. /* Dynamic Stack Routines by Mike Rieser */
  42. void         push(void *object);
  43. void        *pop(void);
  44.  
  45. #define STACK_SIZE    20
  46.  
  47. static struct stack
  48. {
  49.     void       **top, **bottom;
  50. } stack = { (void **) 0, (void **) 0 };
  51.  
  52. /* Functions */
  53.  
  54. /*-
  55.  * Only push() a pointer to the object to be stacked!
  56.  *
  57.  * The first call to push() allocates the stack's memory,
  58.  * and a push() to a full stack increases its size.
  59.  *
  60.  * WARNING:  Modification to an object after a push()
  61.  * will effect the stacked value!
  62.  */
  63. void push(void   *object)
  64. {
  65.     size_t       stack_size = stack.top - stack.bottom;
  66.  
  67.     if (0 == stack_size % STACK_SIZE)
  68.     {
  69.     stack.bottom = (void **) realloc(stack.bottom, sizeof(stack.top)
  70.                      * (stack_size + STACK_SIZE));
  71.     if ((void **) 0 == stack.bottom)
  72.     {
  73.         free(stack.bottom);
  74.         puts("Memory exhausted.");
  75.         clean_exit(10);
  76.     }
  77.     stack.top = stack.bottom + stack_size;
  78.     }
  79.     *stack.top++ = object;        /* increment the top of the stack */
  80.     return;
  81. }
  82.  
  83.  
  84. /*-
  85.  * pop() returns a pointer to the top object on the stack.
  86.  *
  87.  * pop() on the last elment frees the stack's memory.
  88.  *
  89.  * pop() on an empty stack is permitted and returns 0.
  90.  *
  91.  * NOTE: As long as you aren't trying to save NULL pointers,
  92.  * you can use pop() to tell when the stack is empty.
  93.  */
  94. void *pop(void)
  95. {
  96.     void        *object;
  97.  
  98.     if (!stack.bottom)
  99.     return (void *) 0;
  100.  
  101.     object = *--stack.top;
  102.  
  103.     if (stack.top == stack.bottom)
  104.     {
  105.     free(stack.bottom);
  106.     stack.top = stack.bottom = (void **) 0;
  107.     }
  108.     return object;
  109. }
  110.  
  111.  
  112. /*
  113.  * isOldDos - this function checks if the dos version is pre 2.x.
  114.  */
  115. int isOldDOS()
  116. {
  117.     static BOOL  OldDOS = -1;
  118.  
  119.     switch (OldDOS)
  120.     {
  121.     case 0:
  122.     break;
  123.     case 1:
  124.     break;
  125.     default:
  126.     {
  127.         struct Library *DosBase;
  128.  
  129.         if (DosBase = OpenLibrary(DOS_LIBRARY, 37L))
  130.         {
  131.         CloseLibrary(DosBase);
  132.         OldDOS = 0;
  133.         } else
  134.         {
  135.         OldDOS = 1;
  136.         }
  137.     }
  138.     }
  139.  
  140.     return OldDOS;
  141. }
  142.  
  143.  
  144. /*
  145.  * matchwild - pushes filenames which match the given pattern.
  146.  * it also returns a count of the matches found.
  147. */
  148. int matchwild(char *pattern)
  149. {
  150.     static char *special = "#?*%([|";    /* )] */
  151.     struct AnchorPath *APath;
  152.     int          matches = 0;
  153.     LONG         error;
  154.  
  155.     /* Check if correct OS */
  156.     if (isOldDOS())
  157.     return;
  158.  
  159.     /* Check if pattern is special */
  160.     if (!(strpbrk(pattern, special)))
  161.     return;
  162.  
  163.     APath = AllocMem(sizeof(struct AnchorPath) + BLKSIZE, MEMF_CLEAR);
  164.  
  165.     if (!(APath))
  166.     return;
  167.  
  168.     APath->ap_Strlen = BLKSIZE;
  169.     APath->ap_BreakBits = SIGBREAKF_CTRL_C;
  170.  
  171.     if ((error = MatchFirst((UBYTE *) pattern, APath)) == 0)
  172.     {
  173.     do
  174.     {
  175.         ++matches;
  176.         push(strdup((char *) APath->ap_Buf));
  177.     }
  178.     while ((error = MatchNext(APath)) == 0);
  179.     }
  180.     MatchEnd(APath);
  181.  
  182.     if (error != ERROR_NO_MORE_ENTRIES)
  183.     {
  184.     PrintFault(error, NULL);
  185.     }
  186.     FreeMem(APath, sizeof(struct AnchorPath) + BLKSIZE);
  187.  
  188.     return matches;
  189. }
  190.  
  191.  
  192. /*
  193.  * expand -- returns new char **argv to replace previous one. It also adjusts
  194.  * argc.
  195.  * 
  196.  * NOTE: The calling function really needs to free each element.
  197.  */
  198. char **expand(int  *argc, char **argv)
  199. {
  200.     int          i;
  201.     static char *special = "#?*%([|";    /* )] */
  202.  
  203.     for (i = 0; i < *argc; ++i)
  204.     {
  205.     if (strpbrk(argv[i], special))
  206.     {
  207.         matchwild(argv[i]);        /* expands the wildcard pattern */
  208.     } else
  209.     {
  210.         push(strdup(argv[i]));    /* Make sure nobody frees memory twice */
  211.     }
  212.     }
  213.  
  214.     *argc = stack.top - stack.bottom;
  215.     return stack.bottom;
  216. }
  217.  
  218.  
  219. /*
  220.  * This is something I wish I didn't have to participate in.
  221.  *
  222.  * wildcard - returns filename arguments in one string 
  223.  * separated by spaces.
  224.  */
  225. char *wildcard(char *names)
  226. {
  227.     int          i, count;
  228.     char        *pc, *buf;
  229.  
  230.     buf = strdup(names);
  231.     if (0 == (count = matchwild(names)))
  232.     {
  233.     strcpy(names, buf);
  234.     free(buf);
  235.     return names;
  236.     }
  237.     free(buf);
  238.  
  239.     buf = tmpblk.c;
  240.     for (i = 0; i < count; ++i)
  241.     {
  242.     buf += sprintf(buf, "%s ", pc = pop());
  243.     free(pc);
  244.     }
  245.  
  246.     return tmpblk.c;
  247. }
  248.  
  249.  
  250. #ifndef AZTEC_C
  251.  
  252. /*
  253.  * strdup -- copies a string into a safe place.
  254.  */
  255. char *strdup(char *str)
  256. {
  257.     char        *dup = (char *) malloc(strlen(str) + 1);
  258.  
  259.     return (dup) ? strcpy(dup, str) : (char *) 0;    /* returns dup */
  260. }
  261.  
  262. #endif
  263.  
  264.  
  265. /*
  266.  * Replace main by one that will expand the arg list.
  267.  */
  268. void main(int argc, char **argv)
  269. {
  270.     char       **nargv;
  271.  
  272.     if (argc == 0)
  273.         if (Output() == 0)
  274.         exit(1);    /* ran from WorkBench with no window */
  275.  
  276.     nargv = expand(&argc, argv);
  277.  
  278.     (void) _user_main(argc, nargv);
  279.     (void) clean_exit(0);
  280. }
  281.  
  282.  
  283. clean_exit(int val)
  284. {
  285.     void        *pc;
  286.  
  287.     while (pc = pop())
  288.     free(pc);
  289.     exit(val);
  290. }
  291.  
  292. #define main    _user_main
  293. #define exit    clean_exit
  294.