history.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. /**********************************************************************
  2. *
  3. * G_read_history (name, mapset, phist)
  4. * char *name name of map
  5. * char *mapset mapset that map belongs to
  6. * struct History *phist structure to hold history info
  7. *
  8. * Reads the history information associated with map layer "map"
  9. * in mapset "mapset" into the structure "phist".
  10. *
  11. * returns: 0 if successful
  12. * -1 on fail
  13. *
  14. * note: a warning message is printed if the file is incorrect
  15. *
  16. **********************************************************************
  17. *
  18. * G_write_history (name, phist)
  19. * char *name name of map
  20. * struct History *phist structure holding history info
  21. *
  22. * Writes the history information associated with map layer "map"
  23. * into current from the structure "phist".
  24. *
  25. * returns: 0 if successful
  26. * -1 on fail
  27. ***********************************************************************
  28. *
  29. * G_short_history (name, type, hist)
  30. * char *name name of cell file
  31. * char *type type of cell file
  32. * struct History *hist History structure to be filled in
  33. *
  34. * Puts local information like time and date, user's name, map name,
  35. * and current mapset name into the hist structure
  36. *
  37. * NOTE: use G_write_history() to write the structure.
  38. **********************************************************************
  39. *
  40. * G_command_history (hist)
  41. * struct History *hist History structure to be filled in
  42. *
  43. * Appends (parsed) command line to history structure's comments
  44. *
  45. * Returns:
  46. * 0 success
  47. * 1 failure (history file full, no change)
  48. * 2 failure (history file full, added as much as we could)
  49. *
  50. * NOTE: initialize structure with G_short_history() first.
  51. * NOTE: use G_write_history() to write the structure.
  52. **********************************************************************/
  53. #include <string.h>
  54. #include <grass/gis.h>
  55. #include <grass/glocale.h>
  56. /*!
  57. * \brief read raster history file
  58. *
  59. * This routine reads the history file for
  60. * the raster map <b>name</b> in <b>mapset</b> into the <b>history</b>
  61. * structure.
  62. * A diagnostic message is printed and -1 is returned if there is an error
  63. * reading the history file. Otherwise, 0 is returned.
  64. *
  65. * \param name
  66. * \param mapset
  67. * \param history
  68. * \return int
  69. */
  70. int G_read_history(const char *name, const char *mapset, struct History *hist)
  71. {
  72. FILE *fd;
  73. G_zero(hist, sizeof(struct History));
  74. fd = G_fopen_old("hist", name, mapset);
  75. if (!fd)
  76. goto error;
  77. if (!G_getl(hist->mapid, sizeof(hist->mapid), fd))
  78. goto error;
  79. G_ascii_check(hist->mapid);
  80. if (!G_getl(hist->title, sizeof(hist->title), fd))
  81. goto error;
  82. G_ascii_check(hist->title);
  83. if (!G_getl(hist->mapset, sizeof(hist->mapset), fd))
  84. goto error;
  85. G_ascii_check(hist->mapset);
  86. if (!G_getl(hist->creator, sizeof(hist->creator), fd))
  87. goto error;
  88. G_ascii_check(hist->creator);
  89. if (!G_getl(hist->maptype, sizeof(hist->maptype), fd))
  90. goto error;
  91. G_ascii_check(hist->maptype);
  92. if (!G_getl(hist->datsrc_1, sizeof(hist->datsrc_1), fd))
  93. goto error;
  94. G_ascii_check(hist->datsrc_1);
  95. if (!G_getl(hist->datsrc_2, sizeof(hist->datsrc_2), fd))
  96. goto error;
  97. G_ascii_check(hist->datsrc_2);
  98. if (!G_getl(hist->keywrd, sizeof(hist->keywrd), fd))
  99. goto error;
  100. G_ascii_check(hist->keywrd);
  101. hist->edlinecnt = 0;
  102. while ((hist->edlinecnt < MAXEDLINES) &&
  103. (G_getl
  104. (hist->edhist[hist->edlinecnt], sizeof(hist->edhist[0]), fd))) {
  105. G_ascii_check(hist->edhist[hist->edlinecnt]);
  106. hist->edlinecnt++;
  107. }
  108. fclose(fd);
  109. return 0;
  110. error:
  111. if (fd != NULL)
  112. fclose(fd);
  113. G_warning(_("can't get history information for [%s] in mapset [%s]"),
  114. name, mapset);
  115. return -1;
  116. }
  117. /*!
  118. * \brief write raster history file
  119. *
  120. * This routine writes the history file for the raster map
  121. * <b>name</b> in the current mapset from the <b>history</b> structure.
  122. * A diagnostic message is printed and -1 is returned if there is an error
  123. * writing the history file. Otherwise, 0 is returned.
  124. * <b>Note.</b> The <b>history</b> structure should first be initialized
  125. * using <i>G_short_history.</i>
  126. *
  127. * \param name
  128. * \param history
  129. * \return int
  130. */
  131. int G_write_history(const char *name, struct History *hist)
  132. {
  133. FILE *fd;
  134. int i;
  135. fd = G_fopen_new("hist", name);
  136. if (!fd)
  137. goto error;
  138. fprintf(fd, "%s\n", hist->mapid);
  139. fprintf(fd, "%s\n", hist->title);
  140. fprintf(fd, "%s\n", hist->mapset);
  141. fprintf(fd, "%s\n", hist->creator);
  142. fprintf(fd, "%s\n", hist->maptype);
  143. fprintf(fd, "%s\n", hist->datsrc_1);
  144. fprintf(fd, "%s\n", hist->datsrc_2);
  145. fprintf(fd, "%s\n", hist->keywrd);
  146. for (i = 0; i < hist->edlinecnt; i++)
  147. fprintf(fd, "%s\n", hist->edhist[i]);
  148. fclose(fd);
  149. return 0;
  150. error:
  151. if (fd)
  152. fclose(fd);
  153. G_warning(_("can't write history information for [%s]"), name);
  154. return -1;
  155. }
  156. /*!
  157. * \brief initialize history structure
  158. *
  159. * This routine initializes the
  160. * <b>history</b> structure, recording the date, user, module name and the
  161. * raster map <b>name</b> structure. The <b>type</b> is an anachronism from
  162. * earlier versions of GRASS and should be specified as "raster".
  163. * <b>Note.</b> This routine only initializes the data structure. It does not
  164. * write the history file.
  165. *
  166. * \param name
  167. * \param type
  168. * \param history
  169. * \return int
  170. */
  171. int G_short_history(const char *name, const char *type, struct History *hist)
  172. {
  173. strncpy(hist->mapid, G_date(), RECORD_LEN);
  174. strncpy(hist->title, name, RECORD_LEN);
  175. strncpy(hist->mapset, G_mapset(), RECORD_LEN);
  176. strncpy(hist->creator, G_whoami(), RECORD_LEN);
  177. strncpy(hist->maptype, type, RECORD_LEN);
  178. sprintf(hist->keywrd, "generated by %s", G_program_name());
  179. strcpy(hist->datsrc_1, "");
  180. strcpy(hist->datsrc_2, "");
  181. hist->edlinecnt = 0;
  182. return 1;
  183. }
  184. /*!
  185. * \brief Save command line to raster history structure
  186. *
  187. * This routine takes an existing (run <i>G_short_history first</i>) history
  188. * structure and adds the command line to the end of the comments array, as
  189. * cleaned & expanded by the parser.
  190. *
  191. * History file is limited to [80]x[50], as defined in include/gis.h
  192. *
  193. * * First version had for loops of [i][j] character assignments and ending
  194. * nulls, but using the string libraries is cleaner and less bug prone.
  195. * * Second version had white space detection, intelligent wrapping, and
  196. * indentation of continued lines, but this proved a pain in the neck for
  197. * things like r.patch which can have long strings without any
  198. * parser-acceptable breaks.
  199. * * This is MK-III, simplified, but that's good: it's cut & paste-able.
  200. *
  201. * NOTE: use G_write_history() to write the structure.
  202. *
  203. * Sample Usage:
  204. *
  205. * struct History history;
  206. * G_short_history(rasterfile, "raster", &history);
  207. * G_command_history(&history);
  208. * G_write_history(rasterfile, &history);
  209. *
  210. * Returns:
  211. * 0 success
  212. * 1 failure (history file full, no change)
  213. * 2 failure (history file full, added as much as we could)
  214. *
  215. * \param history
  216. * \return int
  217. *
  218. */
  219. int G_command_history(struct History *hist)
  220. {
  221. int j, cmdlen;
  222. char *cmdlin;
  223. cmdlin = G_recreate_command();
  224. cmdlen = strlen(cmdlin);
  225. if (hist->edlinecnt > MAXEDLINES - 2) {
  226. G_warning(_("Not enough room in history file to record command line."));
  227. return 1;
  228. }
  229. if (hist->edlinecnt > 0) { /* add a blank line if preceding history exists */
  230. strcpy(hist->edhist[hist->edlinecnt], "");
  231. hist->edlinecnt++;
  232. }
  233. if (cmdlen < 70) { /* ie if it will fit on a single line */
  234. sprintf(hist->edhist[hist->edlinecnt], G_recreate_command());
  235. hist->edlinecnt++;
  236. }
  237. else { /* multi-line required */
  238. j = 0; /* j is the current position in the command line string */
  239. while ((cmdlen - j) > 70) {
  240. strncpy(hist->edhist[hist->edlinecnt], &cmdlin[j], 68);
  241. hist->edhist[hist->edlinecnt][68] = '\0';
  242. strcat(hist->edhist[hist->edlinecnt], "\\");
  243. j += 68;
  244. hist->edlinecnt++;
  245. if (hist->edlinecnt > MAXEDLINES - 2) {
  246. G_warning(_("Not enough room in history file for command line (truncated)."));
  247. return 2;
  248. }
  249. }
  250. if ((cmdlen - j) > 0) { /* ie anything left */
  251. strcpy(hist->edhist[hist->edlinecnt], &cmdlin[j]);
  252. hist->edlinecnt++;
  253. }
  254. }
  255. return 0;
  256. }