getflags.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "rc.h"
  10. #include "getflags.h"
  11. #include "fns.h"
  12. char *flagset[] = {"<flag>"};
  13. char **flag[NFLAG];
  14. char *cmdname;
  15. static char *flagarg="";
  16. static void reverse(char**, char**);
  17. static int scanflag(int, char*);
  18. static void errn(char*, int);
  19. static void errs(char*);
  20. static void errc(int);
  21. static int reason;
  22. #define RESET 1
  23. #define FEWARGS 2
  24. #define FLAGSYN 3
  25. #define BADFLAG 4
  26. static int badflag;
  27. int
  28. getflags(int argc, char *argv[], char *flags, int stop)
  29. {
  30. char *s;
  31. int i, j, c, count;
  32. flagarg = flags;
  33. if(cmdname==0)
  34. cmdname = argv[0];
  35. i = 1;
  36. while(i!=argc){
  37. if(argv[i][0] != '-' || argv[i][1] == '\0'){
  38. if(stop) /* always true in rc */
  39. return argc;
  40. i++;
  41. continue;
  42. }
  43. s = argv[i]+1;
  44. while(*s){
  45. c=*s++;
  46. count = scanflag(c, flags);
  47. if(count==-1)
  48. return -1;
  49. if(flag[c]){ reason = RESET; badflag = c; return -1; }
  50. if(count==0){
  51. flag[c] = flagset;
  52. if(*s=='\0'){
  53. for(j = i+1;j<=argc;j++)
  54. argv[j-1] = argv[j];
  55. --argc;
  56. }
  57. }
  58. else{
  59. if(*s=='\0'){
  60. for(j = i+1;j<=argc;j++)
  61. argv[j-1] = argv[j];
  62. --argc;
  63. s = argv[i];
  64. }
  65. if(argc-i<count){
  66. reason = FEWARGS;
  67. badflag = c;
  68. return -1;
  69. }
  70. reverse(argv+i, argv+argc);
  71. reverse(argv+i, argv+argc-count);
  72. reverse(argv+argc-count+1, argv+argc);
  73. argc-=count;
  74. flag[c] = argv+argc+1;
  75. flag[c][0] = s;
  76. s="";
  77. }
  78. }
  79. }
  80. return argc;
  81. }
  82. static void
  83. reverse(char **p, char **q)
  84. {
  85. char *t;
  86. for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
  87. }
  88. static int
  89. scanflag(int c, char *f)
  90. {
  91. int fc, count;
  92. if(0<=c && c<NFLAG)
  93. while(*f){
  94. if(*f==' '){
  95. f++;
  96. continue;
  97. }
  98. fc=*f++;
  99. if(*f==':'){
  100. f++;
  101. if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
  102. count = 0;
  103. while('0'<=*f && *f<='9') count = count*10+*f++-'0';
  104. }
  105. else
  106. count = 0;
  107. if(*f=='['){
  108. do{
  109. f++;
  110. if(*f=='\0'){ reason = FLAGSYN; return -1; }
  111. }while(*f!=']');
  112. f++;
  113. }
  114. if(c==fc)
  115. return count;
  116. }
  117. reason = BADFLAG;
  118. badflag = c;
  119. return -1;
  120. }
  121. void
  122. usage(char *tail)
  123. {
  124. char *s, *t, c;
  125. int count, nflag = 0;
  126. switch(reason){
  127. case RESET:
  128. errs("Flag -");
  129. errc(badflag);
  130. errs(": set twice\n");
  131. break;
  132. case FEWARGS:
  133. errs("Flag -");
  134. errc(badflag);
  135. errs(": too few arguments\n");
  136. break;
  137. case FLAGSYN:
  138. errs("Bad argument to getflags!\n");
  139. break;
  140. case BADFLAG:
  141. errs("Illegal flag -");
  142. errc(badflag);
  143. errc('\n');
  144. break;
  145. }
  146. errs("Usage: ");
  147. errs(cmdname);
  148. for(s = flagarg;*s;){
  149. c=*s;
  150. if(*s++==' ')
  151. continue;
  152. if(*s==':'){
  153. s++;
  154. count = 0;
  155. while('0'<=*s && *s<='9') count = count*10+*s++-'0';
  156. }
  157. else count = 0;
  158. if(count==0){
  159. if(nflag==0)
  160. errs(" [-");
  161. nflag++;
  162. errc(c);
  163. }
  164. if(*s=='['){
  165. s++;
  166. while(*s!=']' && *s!='\0') s++;
  167. if(*s==']')
  168. s++;
  169. }
  170. }
  171. if(nflag)
  172. errs("]");
  173. for(s = flagarg;*s;){
  174. c=*s;
  175. if(*s++==' ')
  176. continue;
  177. if(*s==':'){
  178. s++;
  179. count = 0;
  180. while('0'<=*s && *s<='9') count = count*10+*s++-'0';
  181. }
  182. else count = 0;
  183. if(count!=0){
  184. errs(" [-");
  185. errc(c);
  186. if(*s=='['){
  187. s++;
  188. t = s;
  189. while(*s!=']' && *s!='\0') s++;
  190. errs(" ");
  191. errn(t, s-t);
  192. if(*s==']')
  193. s++;
  194. }
  195. else
  196. while(count--) errs(" arg");
  197. errs("]");
  198. }
  199. else if(*s=='['){
  200. s++;
  201. while(*s!=']' && *s!='\0') s++;
  202. if(*s==']')
  203. s++;
  204. }
  205. }
  206. if(tail){
  207. errs(" ");
  208. errs(tail);
  209. }
  210. errs("\n");
  211. Exit("bad flags");
  212. }
  213. static void
  214. errn(char *s, int count)
  215. {
  216. while(count){ errc(*s++); --count; }
  217. }
  218. static void
  219. errs(char *s)
  220. {
  221. while(*s) errc(*s++);
  222. }
  223. #define NBUF 80
  224. static char buf[NBUF], *bufp = buf;
  225. static void
  226. errc(int c)
  227. {
  228. *bufp++=c;
  229. if(bufp==&buf[NBUF] || c=='\n'){
  230. Write(2, buf, bufp-buf);
  231. bufp = buf;
  232. }
  233. }