getflags.c 3.9 KB

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