parse.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <grass/glocale.h>
  5. #include "global.h"
  6. int parse_units();
  7. int parse_option();
  8. int match();
  9. int parse_command_line(int argc, char *argv[])
  10. {
  11. int ncols;
  12. struct
  13. {
  14. struct Option *vect;
  15. struct Option *option;
  16. struct Option *type;
  17. struct Option *field;
  18. struct Option *qfield;
  19. struct Option *col;
  20. struct Option *units;
  21. struct Option *qcol;
  22. struct Option *fs;
  23. } parms;
  24. struct
  25. {
  26. struct Flag *p, *s, *t;
  27. } flags;
  28. char *desc;
  29. parms.vect = G_define_standard_option(G_OPT_V_MAP);
  30. parms.field = G_define_standard_option(G_OPT_V_FIELD);
  31. parms.field->label = _("Layer number or name (write to)");
  32. parms.type = G_define_standard_option(G_OPT_V_TYPE);
  33. parms.type->options = "point,line,boundary,centroid";
  34. parms.type->answer = "point,line,boundary,centroid";
  35. parms.type->label = _("Feature type");
  36. parms.type->description =
  37. _("For coor valid point/centroid, "
  38. "for length valid line/boundary");
  39. parms.type->guisection = _("Selection");
  40. parms.option = G_define_option();
  41. parms.option->key = "option";
  42. parms.option->type = TYPE_STRING;
  43. parms.option->required = YES;
  44. parms.option->multiple = NO;
  45. parms.option->options =
  46. "cat,area,compact,fd,perimeter,length,count,coor,start,end,sides,query,slope,sinuous,azimuth,bbox";
  47. parms.option->description = _("Value to upload");
  48. desc = NULL;
  49. G_asprintf(&desc,
  50. "cat;%s;"
  51. "area;%s;"
  52. "compact;%s;"
  53. "fd;%s;"
  54. "perimeter;%s;"
  55. "length;%s;"
  56. "count;%s;"
  57. "coor;%s;"
  58. "start;%s;"
  59. "end;%s;"
  60. "sides;%s;"
  61. "query;%s;"
  62. "slope;%s;"
  63. "sinuous;%s;"
  64. "azimuth;%s;"
  65. "bbox;%s;",
  66. _("insert new row for each category if doesn't exist yet"),
  67. _("area size"),
  68. _("compactness of an area, calculated as \n"
  69. " compactness = perimeter / (2 * sqrt(PI * area))"),
  70. _("fractal dimension of boundary defining a polygon, calculated as \n"
  71. " fd = 2 * (log(perimeter) / log(area))"),
  72. _("perimeter length of an area"),
  73. _("line length"),
  74. _("number of features for each category"),
  75. _("point coordinates, X,Y or X,Y,Z"),
  76. _("line/boundary starting point coordinates, X,Y or X,Y,Z"),
  77. _("line/boundary end point coordinates, X,Y or X,Y,Z"),
  78. _("categories of areas on the left and right side of the boundary, "
  79. "'query_layer' is used for area category"),
  80. _("result of a database query for all records of the geometry"
  81. "(or geometries) from table specified by 'query_layer' option"),
  82. _("slope steepness of vector line or boundary"),
  83. _("line sinuousity, calculated as line length / distance between end points"),
  84. _("line azimuth, calculated as angle between North direction and endnode direction at startnode"),
  85. _("bounding box of area, N,S,E,W"));
  86. parms.option->descriptions = desc;
  87. parms.col = G_define_standard_option(G_OPT_DB_COLUMNS);
  88. parms.col->label = _("Name of attribute column(s) to populate");
  89. parms.col->required = YES;
  90. parms.units = G_define_standard_option(G_OPT_M_UNITS);
  91. parms.units->options =
  92. "miles,feet,meters,kilometers,acres,hectares,radians,degrees";
  93. parms.qfield = G_define_standard_option(G_OPT_V_FIELD);
  94. parms.qfield->key = "query_layer";
  95. parms.qfield->label = _("Query layer number or name (read from)");
  96. parms.qfield->guisection = _("Query");
  97. parms.qfield->required = NO;
  98. parms.qcol = G_define_standard_option(G_OPT_DB_COLUMN);
  99. parms.qcol->key = "query_column";
  100. parms.qcol->label = _("Name of attribute column used for 'query' option");
  101. parms.qcol->description = _("E.g. 'cat', 'count(*)', 'sum(val)'");
  102. parms.qcol->required = NO;
  103. parms.qcol->guisection = _("Query");
  104. parms.fs = G_define_standard_option(G_OPT_F_SEP);
  105. parms.fs->label = _("Field separator for print mode");
  106. parms.fs->guisection = _("Print");
  107. flags.p = G_define_flag();
  108. flags.p->key = 'p';
  109. flags.p->description = _("Print only");
  110. flags.p->guisection = _("Print");
  111. flags.p->suppress_required = YES;
  112. flags.s = G_define_flag();
  113. flags.s->key = 's';
  114. flags.s->description = _("Only print SQL statements");
  115. flags.s->guisection = _("Print");
  116. flags.t = G_define_flag();
  117. flags.t->key = 'c';
  118. flags.t->description =
  119. _("Print also totals for option length, area, or count");
  120. flags.t->guisection = _("Print");
  121. flags.t->suppress_required = YES;
  122. if (G_parser(argc, argv))
  123. exit(EXIT_FAILURE);
  124. /* check for required options */
  125. if (!parms.vect->answer)
  126. G_fatal_error(_("Required parameter <%s> not set:\n\t(%s)"),
  127. parms.vect->key, parms.vect->description);
  128. if (!parms.option->answer)
  129. G_fatal_error(_("Required parameter <%s> not set:\n\t(%s)"),
  130. parms.option->key, parms.option->description);
  131. options.print = flags.p->answer;
  132. options.sql = flags.s->answer;
  133. options.total = flags.t->answer;
  134. options.name = parms.vect->answer;
  135. options.type = Vect_option_to_types(parms.type);
  136. options.field = atoi(parms.field->answer);
  137. options.qfield = atoi(parms.qfield->answer);
  138. options.option = parse_option(parms.option->answer);
  139. options.units = parse_units(parms.units->answer);
  140. options.fs = G_option_to_separator(parms.fs);
  141. /* Check number of columns */
  142. ncols = 0;
  143. options.col[0] = NULL;
  144. options.col[1] = NULL;
  145. options.col[2] = NULL;
  146. options.col[3] = NULL;
  147. while (parms.col->answers && parms.col->answers[ncols]) {
  148. options.col[ncols] = G_store(parms.col->answers[ncols]);
  149. ncols++;
  150. }
  151. if (!options.print && ! options.total) {
  152. if (options.option == O_AREA || options.option == O_LENGTH || options.option == O_COUNT ||
  153. options.option == O_QUERY || options.option == O_COMPACT || options.option == O_FD ||
  154. options.option == O_PERIMETER || options.option == O_SLOPE || options.option == O_SINUOUS ||
  155. options.option == O_AZIMUTH) { /* one column required */
  156. if (ncols != 1) {
  157. G_fatal_error(_("This option requires one column"));
  158. }
  159. }
  160. else if (options.option == O_SIDES) {
  161. if (ncols != 2) {
  162. G_fatal_error(_("This option requires two columns"));
  163. }
  164. }
  165. else if (options.option == O_COOR || options.option == O_START || options.option == O_END) {
  166. if (ncols < 2) {
  167. G_fatal_error(_("This option requires at least two columns"));
  168. }
  169. }
  170. else if (options.option == O_BBOX) {
  171. if (ncols != 4) {
  172. G_fatal_error(_("This option requires four columns"));
  173. }
  174. }
  175. }
  176. if (options.option == O_QUERY && !parms.qcol->answers)
  177. G_fatal_error(_("Parameter 'qcolumn' must be specified for 'option=query'"));
  178. options.qcol = parms.qcol->answer;
  179. if (options.option == O_SIDES && !(options.type | GV_BOUNDARY))
  180. G_fatal_error(_("The 'sides' option makes sense only for boundaries"));
  181. if (options.option == O_SINUOUS && !(options.type | GV_LINES))
  182. G_fatal_error(_("The 'sinuous' option makes sense only for lines"));
  183. if (options.option == O_AZIMUTH && !(options.type | GV_LINES))
  184. G_fatal_error(_("The 'azimuth' option makes sense only for lines"));
  185. return 0;
  186. }
  187. int parse_units(char *s)
  188. {
  189. int x = 0;
  190. if (match(s, "miles", 2))
  191. x = U_MILES;
  192. else if (match(s, "feet", 1))
  193. x = U_FEET;
  194. else if (match(s, "meters", 2))
  195. x = U_METERS;
  196. else if (match(s, "kilometers", 1))
  197. x = U_KILOMETERS;
  198. else if (match(s, "acres", 1))
  199. x = U_ACRES;
  200. else if (match(s, "hectares", 1))
  201. x = U_HECTARES;
  202. else if (match(s, "radians", 1))
  203. x = U_RADIANS;
  204. else if (match(s, "degrees", 1))
  205. x = U_DEGREES;
  206. return x;
  207. }
  208. int parse_option(char *s)
  209. {
  210. int x = 0;
  211. if (strcmp(s, "cat") == 0)
  212. x = O_CAT;
  213. else if (strcmp(s, "area") == 0)
  214. x = O_AREA;
  215. else if (strcmp(s, "length") == 0)
  216. x = O_LENGTH;
  217. else if (strcmp(s, "count") == 0)
  218. x = O_COUNT;
  219. else if (strcmp(s, "coor") == 0)
  220. x = O_COOR;
  221. else if (strcmp(s, "start") == 0)
  222. x = O_START;
  223. else if (strcmp(s, "end") == 0)
  224. x = O_END;
  225. else if (strcmp(s, "sides") == 0)
  226. x = O_SIDES;
  227. else if (strcmp(s, "query") == 0)
  228. x = O_QUERY;
  229. else if (strcmp(s, "compact") == 0)
  230. x = O_COMPACT;
  231. else if (strcmp(s, "fd") == 0)
  232. x = O_FD;
  233. else if (strcmp(s, "perimeter") == 0)
  234. x = O_PERIMETER;
  235. else if (strcmp(s, "slope") == 0)
  236. x = O_SLOPE;
  237. else if (strcmp(s, "sinuous") == 0)
  238. x = O_SINUOUS;
  239. else if (strcmp(s, "azimuth") == 0)
  240. x = O_AZIMUTH;
  241. else if (strcmp(s, "bbox") == 0)
  242. x = O_BBOX;
  243. return x;
  244. }
  245. int match(char *s, char *key, int min)
  246. {
  247. size_t len;
  248. if (!s)
  249. return 0;
  250. len = strlen(s);
  251. if (len < (size_t) min)
  252. return 0;
  253. return strncmp(s, key, len) == 0;
  254. }