getflags.c 3.7 KB

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