wcalc  2.5
About: Wcalc is a natural-expression command-line calculator.
  Fossies Dox: wcalc-2.5.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

files.c
Go to the documentation of this file.
1 /*
2  * files.c
3  * Wcalc
4  *
5  * Created by Kyle Wheeler on Sat Mar 22 2003.
6  * Copyright (c) 2003 Kyle Wheeler. All rights reserved.
7  *
8  */
9 
10 #ifdef HAVE_CONFIG_H
11 # include "config.h"
12 #endif
13 
14 /* System Headers */
15 #include <fcntl.h> /* for open() */
16 #include <unistd.h> /* for close() */
17 #include <errno.h> /* for errno */
18 #include <sys/types.h> /* for open flags */
19 #include <sys/stat.h> /* for open flags */
20 #include <string.h> /* for strlen() */
21 #include <stdlib.h> /* for free() */
22 #include <assert.h> /* for assert() */
23 #ifdef HAVE_PATH_MAX
24 # ifdef HAVE_LIMITS_H
25 # include <limits.h> /* for PATH_MAX */
26 # endif
27 #endif
28 
29 /* Internal Headers */
30 #include "historyManager.h"
31 #include "string_manip.h"
32 #include "calculator.h"
33 #include "variables.h"
34 #include "output.h"
35 
36 #include "files.h"
37 
38 /* this is for communicating with the scanner */
39 char *open_file = NULL;
40 
41 static inline void tristrncat(char *dest,
42  size_t len,
43  const char *one,
44  const char *two,
45  const char *three)
46 {
47  size_t i;
48  size_t written = 0;
49 
50  strncpy(dest, one, len);
51  for (i = 0; i < len; i++) {
52  if (dest[i] == 0) { break; }
53  }
54  written = i;
55  strncat(dest, two, len - written);
56  for (i = written; i < len; i++) {
57  if (dest[i] == 0) { break; }
58  }
59  written = i;
60  strncat(dest, three, len - written);
61 }
62 
63 int openDotFile(const char *dotFileName,
64  int flags)
65 { /*{{{*/
66  char *filename = NULL;
67  const char *home = getenv("HOME");
68  int namelen;
69  int fd;
70 
71  if (!home) { return -1; }
72  assert(dotFileName);
73  namelen = strlen(home) + strlen(dotFileName) + 3;
74 #ifdef HAVE_PATH_MAX
75  if (namelen > PATH_MAX) {
76  return -2;
77  }
78 #endif
79 
80  filename = malloc(sizeof(char) * namelen + 1);
81  tristrncat(filename, namelen, home, "/.", dotFileName);
82  fd = open(filename, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
83  free(filename);
84  if (fd < 0) {
85  return -3;
86  } else {
87  return fd;
88  }
89 } /*}}}*/
90 
91 int saveState(char *filename)
92 { /*{{{ */
93  int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL,
94  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
95  int return_error = 0;
96 
97  free(filename);
98  if (fd >= 0) {
99  // success
100  size_t hindex;
101  int retval;
102  size_t num_vars = numvars();
103 
104  /* save variables */
105  for (hindex = 0; hindex < num_vars; hindex++) {
106  struct variable *keyval = getrealnvar(hindex);
107  char *cptr;
108 
109  if (!keyval) {
110  continue;
111  }
112  if (!strcmp(keyval->key, "a")) {
113  continue;
114  }
115  retval = write(fd, keyval->key, strlen(keyval->key));
116  if (retval < (int)strlen(keyval->key)) {
117  return_error = errno;
118  break;
119  }
120  retval = write(fd, "=", 1);
121  if (retval < 1) {
122  return_error = errno;
123  break;
124  }
125  if (keyval->exp) {
126  const size_t len = strlen(keyval->expression) + 3;
127  cptr = malloc(len);
128  tristrncat(cptr, len, "'", keyval->expression, "'");
129  } else {
130  cptr = strdup(print_this_result(keyval->value, standard_output, NULL, NULL));
131  }
132  retval = write(fd, cptr, strlen(cptr));
133  if (retval < (int)strlen(cptr)) {
134  return_error = errno;
135  free(cptr);
136  break;
137  }
138  free(cptr);
139  if (keyval->description) {
140  const size_t len = strlen(keyval->expression) + 4;
141  cptr = malloc(len);
142  tristrncat(cptr, len, " '", keyval->description, "'");
143  retval = write(fd, cptr, strlen(cptr));
144  if (retval < (int)strlen(cptr)) {
145  return_error = errno;
146  free(cptr);
147  break;
148  }
149  free(cptr);
150  }
151  retval = write(fd, "\n", 1);
152  if (retval < 1) {
153  return_error = errno;
154  break;
155  }
156  }
157  /* save history */
158  for (hindex = 0; hindex < historyLength() && return_error == 0;
159  hindex++) {
160  char *history_entry = historynum(hindex, 1);
161 
162  retval = write(fd, history_entry, strlen(history_entry));
163  if (retval < (int)strlen(history_entry)) {
164  return_error = errno;
165  break;
166  }
167  retval = write(fd, " # = ", 5);
168  if (retval < 5) {
169  return_error = errno;
170  break;
171  }
172  history_entry = historynum(hindex, 2);
173  retval = write(fd, history_entry, strlen(history_entry));
174  if (retval < (int)strlen(history_entry)) {
175  return_error = errno;
176  break;
177  }
178  retval = write(fd, "\n", 1);
179  if (retval < 1) {
180  return_error = errno;
181  break;
182  }
183  }
184  if (close(fd) != 0) {
185  return_error = errno;
186  }
187  } else {
188  // failure
189  return_error = errno;
190  }
191  return return_error;
192 } /*}}} */
193 
194 int loadStateFD(int fd,
195  const int into_history)
196 { /*{{{*/
197  assert(fd >= 0);
198 
199  int return_error = 0;
200  int standard_output_save = standard_output;
201  standard_output = 0;
202 
203  char *linebuf;
204  int retval;
205  unsigned int linelen = 0, maxlinelen = 99;
206 
207  linebuf = calloc(sizeof(char), 100);
208  retval = read(fd, linebuf + linelen, 1);
209  while (retval == 1) {
210  while (retval == 1 && linebuf[linelen] != '\n') {
211  linelen++;
212  if (linelen == maxlinelen) {
213  char *newlinebuf = realloc(linebuf,
214  sizeof(char) * (maxlinelen +
215  100));
216  if (newlinebuf) {
217  maxlinelen += 100;
218  linebuf = newlinebuf;
219  } else {
220  return_error = errno;
221  retval = -1;
222  break;
223  }
224  }
225  retval = read(fd, linebuf + linelen, 1);
226  }
227  linebuf[linelen] = 0;
228  if (conf.verbose) {
229  display_stateline(linebuf);
230  }
231  stripComments(linebuf);
232  while (linebuf[strlen(linebuf) - 1] == ' ') {
233  linebuf[strlen(linebuf) - 1] = 0;
234  }
235  if (strlen(linebuf)) {
236  extern char *errstring;
237  char *safe;
238 
239  safe = strdup(linebuf);
240  parseme(safe);
241  putval("a", last_answer, "previous answer");
242  if ((!errstring || (errstring && !strlen(errstring)) ||
243  conf.remember_errors) && into_history) {
244  addToHistory(linebuf, last_answer);
245  }
246  free(safe);
247  }
248  linelen = 0;
249  memset(linebuf, 0, maxlinelen);
250  if (retval == 1) {
251  retval = read(fd, linebuf + linelen, 1);
252  }
253  }
254 
255  free(linebuf);
256  standard_output = standard_output_save;
257 
258  return return_error;
259 } /*}}}*/
260 
261 int loadState(const char *filename,
262  const int into_history)
263 { /*{{{ */
264  int fd, return_error = 0;
265 
266  fd = open(filename, O_RDONLY);
267  if (fd < 0) { return_error = errno; }
268  {
269  int tmp = loadStateFD(fd, into_history);
270  if (tmp != 0) {
271  return_error = tmp;
272  }
273  }
274  if (close(fd) != 0) {
275  return_error = errno;
276  }
277 
278  return return_error;
279 } /*}}} */
280 
281 int storeVar(const char *variable)
282 { /*{{{ */
283  int fd, retval = 0, return_error = 0;
284 
285  if (!varexists(variable)) {
286  report_error("Variable is not defined.");
287  return -1;
288  }
289  fd = openDotFile("wcalc_preload", O_WRONLY | O_CREAT | O_APPEND);
290  switch (fd) {
291  case -1:
292  report_error("HOME environment variable unset.");
293  break;
294  case -2:
295  report_error("HOME environment variable is too long.");
296  break;
297  default:
298  {
299  // success
300  struct answer keyval = getvar_full(variable);
301  char *cptr;
302 
303  retval = write(fd, variable, strlen(variable));
304  if (retval < (int)strlen(variable)) {
305  return_error = errno;
306  goto exit_storeVar;
307  }
308  retval = write(fd, "=", 1);
309  if (retval < 1) {
310  return_error = errno;
311  goto exit_storeVar;
312  }
313  if (keyval.exp) {
314  const size_t len = strlen(keyval.exp) + 4;
315  cptr = malloc(len);
316  tristrncat(cptr, len, "'", keyval.exp, "' ");
317  } else {
318  cptr = strdup(print_this_result(keyval.val, standard_output, NULL, NULL));
319  }
320  retval = write(fd, cptr, strlen(cptr));
321  if (retval < (int)strlen(cptr)) {
322  return_error = errno;
323  free(cptr);
324  goto exit_storeVar;
325  }
326  free(cptr);
327  if (keyval.desc) {
328  const size_t len = strlen(keyval.desc) + 3;
329  cptr = malloc(len);
330  tristrncat(cptr, len, "'", keyval.desc, "'");
331  retval = write(fd, cptr, strlen(cptr));
332  if (retval < (int)strlen(cptr)) {
333  return_error = errno;
334  free(cptr);
335  goto exit_storeVar;
336  }
337  free(cptr);
338  }
339  retval = write(fd, "\n", 1);
340  if (retval < 1) {
341  return_error = errno;
342  goto exit_storeVar;
343  }
344  retval = close(fd);
345  if (retval == -1) {
346  return_error = errno;
347  goto exit_storeVar;
348  }
349  }
350  }
351 exit_storeVar:
352  return return_error;
353 } /*}}} */
354 
355 /* vim:set expandtab: */
answer::desc
char * desc
Definition: variables.h:32
conf
struct _conf conf
Definition: calculator.c:111
string_manip.h
calculator.h
display_stateline
void display_stateline(const char *buf)
Definition: main.c:1659
free
void free(void *)
historynum
char * historynum(int step, int col)
Definition: historyManager.c:145
parseme
void parseme(const char *pthis)
Definition: calculator.c:130
variables.h
standard_output
char standard_output
Definition: calculator.c:106
variable::exp
unsigned int exp
Definition: variables.h:25
errstring
char * errstring
Definition: parser.c:111
numvars
size_t numvars(void)
Definition: variables.c:53
variable::description
char * description
Definition: variables.h:23
answer
Definition: variables.h:29
loadState
int loadState(const char *filename, const int into_history)
Definition: files.c:261
getvar_full
struct answer getvar_full(const char *key)
Definition: variables.c:160
openDotFile
int openDotFile(const char *dotFileName, int flags)
Definition: files.c:63
malloc
void * malloc(size_t)
answer::exp
char * exp
Definition: variables.h:31
last_answer
Number last_answer
Definition: calculator.c:98
historyLength
size_t historyLength(void)
Definition: historyManager.c:189
getrealnvar
struct variable * getrealnvar(const size_t n)
Definition: variables.c:127
varexists
int varexists(const char *key)
Definition: variables.c:184
storeVar
int storeVar(const char *variable)
Definition: files.c:281
saveState
int saveState(char *filename)
Definition: files.c:91
print_this_result
char * print_this_result(const Number result, int output, char *nad, char **es)
Definition: calculator.c:926
tristrncat
static void tristrncat(char *dest, size_t len, const char *one, const char *two, const char *three)
Definition: files.c:41
variable::expression
char * expression
Definition: variables.h:22
_conf::verbose
unsigned int verbose
Definition: calculator.h:141
report_error
void report_error(const char *err_fmt,...)
Definition: calculator.c:541
stripComments
void stripComments(char *)
Definition: string_manip.c:119
variable::value
mpfr_t value
Definition: variables.h:24
addToHistory
void addToHistory(char *expression, Number answer)
Definition: historyManager.c:71
variable
Definition: variables.h:20
answer::val
mpfr_t val
Definition: variables.h:30
loadStateFD
int loadStateFD(int fd, const int into_history)
Definition: files.c:194
files.h
historyManager.h
putval
int putval(const char *key, const mpfr_t value, const char *desc)
_conf::remember_errors
unsigned int remember_errors
Definition: calculator.h:135
output.h
open_file
char * open_file
Definition: files.c:39
variable::key
char * key
Definition: variables.h:21