home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume14 / bsd-dyna-link / argv.c next >
Encoding:
C/C++ Source or Header  |  1988-05-08  |  4.5 KB  |  241 lines

  1. #include <ctype.h>
  2. #include <stdio.h>
  3.  
  4. /***********************************************************************
  5. **
  6. ** These routines build argv's.  An "argv" is a null-terminated array
  7. ** of pointers to strings.  Argv's are often declared as char** or
  8. ** char* foo [];
  9. ** 
  10. ** char***
  11. ** argv_new() 
  12. **
  13. **    returns a structure which is a "scaffold" for building up
  14. **    an argv. At any point, the structure will contain an argv in its
  15. **    first field.  If it overflows, a new, larger one is substituted,
  16. **    and the old one discarded.  So don't keep direct references to the argv
  17. **    unless you are not going to put any more stuff into it.
  18. **
  19. **    Say 
  20. **         char*** scaffold = (char***)argv_new();
  21. **    
  22. **    Then, when the argv is completed, dereference it...
  23. ** 
  24. **         char** complete_argv = *scaffold;
  25. **
  26. **    Then free the scaffold if you wish...
  27. **
  28. **         cfree(scaffold);
  29. **
  30. **    The argv itself is also allocated by calloc, and may be cfree()'d when
  31. **    it is no longer needed.
  32. **
  33. **    argv_new() returns 0 if it runs out of memory.
  34. **
  35. ** 
  36. ** int
  37. ** argv_put(scaffold, arg) 
  38. **    char*** scaffold;
  39. **    char* arg;
  40. **
  41. **    puts an additional arg into an argv, increasing the size
  42. **    if necessary. Returns 0 on success, -1 if it runs out of memory.
  43. **
  44. ** char**
  45. ** argv_from_str(str)
  46. **   char* str
  47. **
  48. **    Parses a string and builds an argv from it.  It
  49. **    recognizes quote-marks and escapes (\).
  50. **
  51. **    For example,
  52. **
  53. **       foo bar  "foo bar"  '\'foo\''  '"foo"'
  54. **
  55. **    gets parsed into
  56. **
  57. **       foo
  58. **       bar
  59. **       foo bar
  60. **       'foo'
  61. **       "foo"
  62. **       (0)
  63. **
  64. **    The argv and its components are all allocated by calloc().
  65. **    Returns 0 if it runs out of memory.
  66. **    
  67. **
  68. ************************************************************************/
  69.  
  70.  
  71.  
  72. struct argv_rec
  73.   { char** value;
  74.     int size;
  75.     int place;
  76.   };
  77.  
  78.  
  79. argv_put(argv, str)
  80.   struct argv_rec * argv;
  81.   char* str;
  82. {
  83.   if (argv->place + 1 == argv->size) /* oops.. overflow. */
  84.     {
  85.       char** old_argv = argv->value;
  86.       int old_size = argv->size;
  87.  
  88.       argv->size = argv->size *2;
  89.       argv->value = (char**)calloc(1, argv->size*sizeof(char*));
  90.       if(argv->value == 0) { return -1; }
  91.       bcopy(old_argv, argv->value, old_size * sizeof(char*));
  92.       free(old_argv);
  93.     }
  94.  
  95.   argv->value[argv->place] = str;
  96.   argv->place++;
  97.  
  98.   return 0;
  99.  
  100. }
  101.  
  102.  
  103. struct argv_rec *
  104. argv_new()
  105. {
  106.   struct argv_rec* retval = 
  107.     (struct argv_rec*) calloc(1,sizeof(struct argv_rec));
  108.   if (retval == 0) return 0;
  109.  
  110.   retval->value = (char**)calloc(1, 2*sizeof(char*));
  111.   if(retval->value == 0) { free(retval); return 0; }
  112.  
  113.   retval->size = 2;
  114.   retval->place = 0;
  115.  
  116.   return retval;
  117. }
  118.  
  119.  
  120. static char*
  121. strip(strp)
  122.   char** strp;
  123. {
  124.   char* str = strp? *strp: 0;
  125.   char* buffer;
  126.   char  quote = 0;
  127.   char* next_p;
  128.  
  129.   if(str == 0 || *str == 0) return 0;
  130.  
  131.   buffer = (char*)malloc(strlen(str)+1);
  132.   if(buffer == 0) return 0;
  133.  
  134.   next_p  = buffer;
  135.  
  136.   while (isspace(*str)) str++;
  137.  
  138.   if(*str == '\'' || *str == '"' ) quote = *str++;
  139.  
  140.   while(*str && !(isspace(*str) && !quote) && !(quote && *str == quote))
  141.     {
  142.       if(*str == '\\') str++;
  143.       *next_p++ = *str++;
  144.     }
  145.  
  146.   if(*str && (quote && *str == quote) ) str++; /* skip end-quote */
  147.  
  148.   *next_p = 0;
  149.   { char* retval = (char*)calloc(1, strlen(buffer) +1 );
  150.     if (retval) sprintf(retval, "%s", buffer);
  151.     free(buffer);
  152.     *strp = str;
  153.     return retval;
  154.   }
  155. }
  156.  
  157.  
  158. char**
  159. argv_from_str(str)
  160.   char* str;
  161. {
  162.   struct argv_rec* argv;
  163.   char* next_arg;
  164.   extern errno;
  165.  
  166.   errno = 0;
  167.  
  168.   argv = argv_new();
  169.   if(argv == 0) return 0;
  170.  
  171.   while( (next_arg = strip(&str)) != 0)
  172.     { argv_put(argv, next_arg);
  173.     }
  174.  
  175.   { char** retval = argv->value;
  176.     free(argv);
  177.     return retval;
  178.   }
  179.   
  180.   
  181. }
  182.  
  183. fprintf_argv(fp,argv)
  184.   FILE * fp;
  185.   char** argv;
  186. {
  187.   if(argv)
  188.     while(*argv) fprintf(fp, "%s\n", *argv++);
  189. }
  190.  
  191. printf_argv(argv)
  192.   char** argv;
  193. {
  194.   if(argv)
  195.     while(*argv) printf("%s\n", *argv++);
  196. }
  197.  
  198. int strcmp();
  199.  
  200. static
  201. alcomp(p,q)
  202.   char**p;
  203.   char**q;
  204. {
  205.   return strcmp(*p,*q);
  206. }
  207.  
  208. sort_argv(argc, argv)
  209.   char** argv;
  210. {
  211.  
  212.   qsort(argv, argc, sizeof(char*), alcomp );
  213.  
  214. }
  215.  
  216.  
  217. #undef testing
  218. #ifdef testing
  219. #include <stdio.h>
  220. main(argc, argv)
  221.   char** argv;
  222. {
  223.   char  buf[256];
  224.   char** argy;
  225.   int argk = 0;
  226.   char** aargh;
  227.   scanf("%[^\n]", buf);
  228.   argy = argv_from_str(buf);
  229.  
  230.   aargh = argy;
  231.  
  232.   while(*argy) { printf("%s\n", *argy++ ); fflush(stdout); }
  233.   {
  234.     char** p = aargh;
  235.     while(*p++) argk++;
  236.   }
  237.   sort_argv(argk, aargh);
  238.   while(*aargh) { printf("%s\n", *aargh++ ); fflush(stdout); }
  239. }
  240. #endif testing
  241.