Octopus
oct_f.c
Go to the documentation of this file.
1/*
2 Copyright (C) 2002 M. Marques, A. Castro, A. Rubio, G. Bertsch
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18
19*/
20
21#include <config.h>
22
23#include <assert.h>
24#include <ctype.h>
25#include <libgen.h>
26#include <math.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <time.h>
31#if __has_include(<unistd.h>)
32#include <unistd.h>
33#endif
34
35#include <fortran_types.h>
36
37#ifdef _POSIX_VERSION
38#include <dirent.h>
39#include <sys/stat.h>
40#include <sys/time.h>
41#include <sys/types.h>
42#endif
43
44/* needed for getting executable path on Mac */
45#if defined(__APPLE__) && defined(__MACH__)
46#include <mach-o/dyld.h>
47#endif
49#if defined(__FreeBSD__)
50#include <sys/sysctl.h>
51#endif
52
53#include "string_f.h" /* Fortran <-> c string compatibility issues */
54
55/* *********************** interface functions ********************** */
56
57void FC_FUNC_(oct_mkdir, OCT_MKDIR)(STR_F_TYPE name STR_ARG1) {
58 struct stat buf;
59 char *name_c;
60
61 TO_C_STR1(name, name_c);
62 if (!*name_c)
63 return;
64
65 if (stat(name_c, &buf) == 0) {
66 free(name_c);
67 return;
68 }
69
70#ifndef _WIN32
71 mkdir(name_c, 0775);
72#else
73 mkdir(name_c);
74#endif
75
76 free(name_c);
79void FC_FUNC_(oct_stat, OCT_STAT)(fint *ierr, STR_F_TYPE name,
80 STR_F_TYPE mod_time STR_ARG2) {
81 char *name_c, *mod_time_c;
82 struct stat statbuf;
83 time_t mtime;
84 struct tm *timeinfo;
86 TO_C_STR1(name, name_c);
87 *ierr = stat(name_c, &statbuf);
89 if (*ierr == 0) {
90 mtime = statbuf.st_mtime; /* last modification time */
91 timeinfo = localtime(&mtime);
92 mod_time_c = asctime(timeinfo);
93 } else {
94 perror(name_c); /* what is the problem? */
95 mod_time_c = malloc(sizeof(char));
96 mod_time_c[0] = '\0';
97 }
98 free(name_c);
100 TO_F_STR2(mod_time_c, mod_time);
101 if (*ierr != 0) {
102 printf("ierr = %i\n", *ierr);
103 free(mod_time_c);
105 /* otherwise, do not do this since 'mod_time_c' points at static data of
106 * asctime */
107}
108
109int FC_FUNC_(oct_dir_exists, OCT_DIR_EXISTS)(STR_F_TYPE name STR_ARG1) {
110 int ierr;
111 char *name_c;
112 struct stat statbuf;
113
114 TO_C_STR1(name, name_c);
115 ierr = stat(name_c, &statbuf);
116 free(name_c);
117
118 if (ierr == 0) {
119 return S_ISDIR(statbuf.st_mode);
120 } else {
121 return 0;
122 }
123}
124
125void FC_FUNC_(oct_rm, OCT_RM)(STR_F_TYPE name STR_ARG1) {
126 char *name_c;
128 TO_C_STR1(name, name_c);
129 unlink(name_c);
130 free(name_c);
133void FC_FUNC_(oct_getcwd, OCT_GETCWD)(STR_F_TYPE name STR_ARG1) {
134 char s[256];
135 getcwd(s, 256);
136 TO_F_STR1(s, name);
137}
139void FC_FUNC_(oct_realpath, OCT_REALPATH)(STR_F_TYPE fnam,
140 STR_F_TYPE rnam STR_ARG2) {
141 char *fn = NULL, *rn = NULL;
142 TO_C_STR1(fnam, fn);
143 rn = realpath(fn, NULL);
144 free(fn);
145 if (rn != NULL) {
146 TO_F_STR2(rn, rnam);
147 } else {
148 TO_F_STR2("", rnam);
149 }
150 free(rn);
151 return;
152}
153
154void FC_FUNC_(oct_dirname, OCT_DIRNAME)(STR_F_TYPE fnam,
155 STR_F_TYPE dnam STR_ARG2) {
156 char *fn = NULL, *dn = NULL;
157 TO_C_STR1(fnam, fn);
158 dn = dirname(fn);
159 if (dn != NULL) {
160 TO_F_STR2(dn, dnam);
161 } else {
162 TO_F_STR2("", dnam);
164 free(fn);
165 return;
168void FC_FUNC_(oct_basename, OCT_BASENAME)(STR_F_TYPE fnam,
169 STR_F_TYPE bnam STR_ARG2) {
170 char *fn = NULL, *bn = NULL;
171 TO_C_STR1(fnam, fn);
172 bn = basename(fn);
173 free(fn);
174 if (bn != NULL) {
175 TO_F_STR2(bn, bnam);
176 } else {
177 TO_F_STR2("", bnam);
178 }
179 return;
180}
182void FC_FUNC_(oct_getenv, OCT_GETENV)(STR_F_TYPE var,
183 STR_F_TYPE value STR_ARG2) {
184 char *name_c, *var_c;
186 TO_C_STR1(var, name_c);
187 var_c = getenv(name_c);
188 free(name_c);
190 if (var_c != NULL) {
191 TO_F_STR2(var_c, value);
192 } else {
193 TO_F_STR2("", value);
194 }
195}
196
197/* this function gets a string of the form '1-12, 34' and fills
198 array l with the 1 if the number is in the list, or 0 otherwise */
199void FC_FUNC_(oct_wfs_list, OCT_WFS_LIST)(STR_F_TYPE str,
200 fint l[16384] STR_ARG1) {
201 int i, i1, i2;
202 char c[20], *c1, *str_c, *s;
203
204 TO_C_STR1(str, str_c);
205 s = str_c;
206
207 /* clear list */
208 for (i = 0; i < 16384; i++)
209 l[i] = 0;
210
211 while (*s) {
212 /* get integer */
213 for (c1 = c; isdigit(*s) || isspace(*s); s++)
214 if (isdigit(*s))
215 *c1++ = *s;
216 *c1 = '\0';
217 i1 = atoi(c) - 1;
219 if (*s == '-') { /* range */
220 s++;
221 for (c1 = c; isdigit(*s) || isspace(*s); s++)
222 if (isdigit(*s))
223 *c1++ = *s;
224 *c1 = '\0';
225 i2 = atoi(c) - 1;
226 } else /* single value */
227 i2 = i1;
228
229 for (i = i1; i <= i2; i++)
230 if (i >= 0 && i < 16384)
231 l[i] = 1;
232
233 if (*s)
234 s++;
235 }
236
237 free(str_c);
238}
239
240/* ------------------------------ from varia.c -------------------------------
241 */
242#include "varia.h"
243
244void FC_FUNC_(oct_progress_bar, OCT_PROGRESS_BAR)(fint *a, fint *max) {
245 if (*max == 0)
246 return; /* Skip the bar if the length is 0 */
247 progress_bar(*a, *max);
248}
249
250/* ------------------------------ some stuff --------------------------------
251 */
252void FC_FUNC_(oct_gettimeofday, OCT_GETTIMEOFDAY)(fint *sec, fint *usec) {
253#ifdef _POSIX_VERSION
254 struct timeval tv;
255
256 gettimeofday(&tv, NULL);
257
258 /* The typecast below should use long. However, this causes incompatibilities
259 with Fortran integers.
260 Using int will cause wrong results when tv.tv_sec exceeds
261 INT_MAX=2147483647 */
262 *sec = (int)tv.tv_sec;
263 *usec = (int)tv.tv_usec;
264/*
265 char str[sizeof("HH:MM:SS")];
266 time_t local;
267 local = tv.tv_sec;
268 strftime(str, sizeof(str), "%T", localtime(&local));
269 printf("%s.%06ld \n", str, (long) tv.tv_usec);
270 printf("%ld.%06ld \n", (long) tv.tv_sec, (long) tv.tv_usec);
271*/
272#else
273 *sec = 0;
274 *usec = 0;
275#endif
276}
277
278double FC_FUNC_(oct_clock, OCT_CLOCK)() {
279#ifdef _POSIX_VERSION
280 int sec, usec;
281 FC_FUNC_(oct_gettimeofday, OCT_GETTIMEOFDAY)(&sec, &usec);
282 return sec + 1.0e-6 * usec;
283#else
284 return (double)clock() / CLOCKS_PER_SEC;
285#endif
286}
287
288void FC_FUNC_(oct_nanosleep, OCT_NANOSLEEP)(fint *sec, fint *nsec) {
289#ifdef _POSIX_VERSION
290 /* Datatypes should be long instead of int (see comment in gettimeofday) */
291 struct timespec req;
292 req.tv_sec = (time_t)*sec;
293 req.tv_nsec = (long)*nsec;
294 nanosleep(&req, NULL);
295#endif
296}
297
298void FC_FUNC_(oct_sysname, OCT_SYSNAME)(STR_F_TYPE name STR_ARG1) {
299 char *name_c;
300
301 sysname(&name_c);
302 TO_F_STR1(name_c, name);
303 free(name_c);
304}
305
306int FC_FUNC_(oct_number_of_lines,
307 OCT_NUMBER_OF_LINES)(STR_F_TYPE name STR_ARG1) {
308
309 FILE *pf;
310 int c, i;
311 char *name_c;
312
313 TO_C_STR1(name, name_c);
314 pf = fopen(name_c, "r");
315 free(name_c);
316
317 if (pf != NULL) {
318 i = 0;
319 while ((c = getc(pf)) != EOF) {
320 if (c == '\n')
321 i++;
322 }
323 fclose(pf);
324 return i;
325 } else {
326 return -1;
327 }
328}
329
330/* Given a string in C, it breaks it line by line and returns each
331 as a Fortran string. Returns 0 if string does not have more lines.
332*/
333void FC_FUNC_(oct_break_c_string,
334 OCT_BREAK_C_STRING)(char **str, char **s,
335 STR_F_TYPE line_f STR_ARG1) {
336 char *c, line[256]; /* hopefully no line is longer than 256 characters ;) */
337
338 if (*s == NULL)
339 *s = *str;
340
341 if (*s == NULL || **s == '\0') {
342 *s = (char *)(0);
343 return;
344 }
345
346 for (c = line; **s != '\0' && **s != '\n'; (*s)++, c++)
347 *c = **s;
348 *c = '\0';
349 if (**s == '\n')
350 (*s)++;
351
352 TO_F_STR1(line, line_f);
353}
354
355/*
356
357This function searches in directory given by dirname all files that have the
358following name:
359
360*_<real_number>_<integer>*
361
362It returns the value of <real_number> found that is closest to freq (or
363abs(freq)) and for which the value of <integer> matches with the tag argument.
364
365The value found is returned in the freq argument.
366
367ierr results:
3680 : value found
3691 : no matching file found
3702 : cannot open the directory or function not available
371
372*/
373
374void FC_FUNC_(oct_search_file_lr,
375 OCT_SEARCH_FILE_LR)(double *freq, const fint *tag, fint *ierr,
376 STR_F_TYPE dirname STR_ARG1) {
377#ifdef _POSIX_VERSION
378
379 DIR *dir;
380 struct dirent *ent;
381 char *name_c;
382 char *num_start, *num_end;
383 double read_value, min;
384 int found_something, read_tag;
385
386 TO_C_STR1(dirname, name_c);
387 dir = opendir(name_c);
388
389 if (dir == NULL) {
390 *ierr = 2;
391 return;
392 }
393 free(name_c);
394
395 ent = NULL;
396 found_something = 0;
397
398 while (1) {
399 ent = readdir(dir);
400 if (ent == NULL)
401 break;
402
403 num_start = strchr(ent->d_name, '_');
404
405 if (num_start != NULL) {
406 num_start++; /* now this points to the beginning of the number */
407
408 /* take the numerical value from the string */
409 read_value = strtod(num_start, &num_end);
410
411 if (num_end == num_start)
412 continue; /* no number found */
413
414 /* check that we have the correct tag */
415 if (num_end[0] == '_') {
416
417 num_start = num_end + 1;
418 read_tag = (int)strtol(num_start, &num_end, 10);
419 if (num_end == num_start)
420 continue; /* no tag found */
421 if (read_tag != *tag)
422 continue; /* tag does not match */
423
424 } else
425 continue;
426
427 /* if this is the first number we found */
428 if (!found_something) {
429 min = read_value;
430 found_something = 1;
431 } else if (fabs(fabs(min) - fabs(*freq)) >
432 fabs(fabs(read_value) - fabs(*freq))) {
433 /* if the value is closer than previous */
434 min = read_value;
435 }
436 }
437 }
438
439 closedir(dir);
440
441 if (found_something) {
442 *ierr = 0;
443 *freq = min;
444 } else {
445 *ierr = 1;
446 }
447
448#else
449#warning directory search not compiled
450 fprintf(stderr, "Warning: Directory search not available since certain C "
451 "functions are not available.\n");
452 *ierr = 2;
453#endif
454}
455
456void *FC_FUNC_(oct_get_memory_usage, OCT_GET_MEMORY_USAGE)() {
457#ifdef _POSIX_VERSION
458 static size_t pagesize = 0;
459 FILE *f;
460 int pid;
461 unsigned long mem;
462 char s[256];
463
464 if (pagesize == 0)
465 pagesize = sysconf(_SC_PAGESIZE);
466
467 pid = getpid();
468 sprintf(s, "%s%d%s", "/proc/", pid, "/statm");
469 if ((f = fopen(s, "r")) == (FILE *)NULL)
470 return (void *)(-1);
471 fscanf(f, "%lu", &mem);
472 fclose(f);
473
474 return (void *)(mem * pagesize);
475#else
476 return 0;
477#endif
478}
479
480/* Get the path to the current executable. As there is no portable solution,
481 * we need a different implementation for Linux and Mac (and possible other OSs) */
482void FC_FUNC_(oct_executable_path, OCT_EXECUTABLE_PATH)(STR_F_TYPE fpath STR_ARG1) {
483 char *path = NULL;
484#if defined(__APPLE__) && defined(__MACH__)
485 char *buf = NULL;
486 uint32_t bufsize = 0;
487 int ret = 0;
488 ret = _NSGetExecutablePath(buf, &bufsize);
489 assert(ret == -1);
490 buf = (char *)malloc(bufsize);
491 assert(buf != NULL);
492 ret = _NSGetExecutablePath(buf, &bufsize);
493 assert(ret == 0);
494 path = realpath(buf, NULL);
495 free(buf);
496#elif defined(linux) || defined(__linux)
497 path = realpath("/proc/self/exe", NULL);
498#elif defined(__NETBSD__) || defined(__NetBSD__)
499 path = realpath("/proc/curproc/exe", NULL);
500#elif defined(__DragonFly__)
501 path = realpath("/proc/curproc/file", NULL);
502#elif defined(__FreeBSD__)
503 int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
504 size_t len = 0;
505 int ret = 0;
506 ret = sysctl(mib, 4, NULL, &len, NULL, 0);
507 assert(ret == 0);
508 path = malloc(len);
509 assert(path != NULL);
510 ret = sysctl(mib, 4, path, &len, NULL, 0);
511 assert(ret == 0);
512#else
513 /* if OS is not recognized, return empty string - in the calling code, this is then ignored */
514 path = (char *)malloc(1);
515 assert(path != NULL);
516 path[0] = '\0';
517#endif
518 if (path == NULL) {
519 fprintf(stderr, "%s:%d: in %s: Something went wrong\n", __FILE__, __LINE__, __func__);
520 path = (char *)malloc(1);
521 assert(path != NULL);
522 path[0] = '\0';
523 }
524 TO_F_STR1(path, fpath);
525 free(path);
526 return;
527}
char * getcwd(char *__buf, size_t __size) __attribute__((__nothrow__
int fint
Definition: fortran_types.h:14
__uint32_t uint32_t
Definition: io_binary.c:1336
double fabs(double __x) __attribute__((__nothrow__
__time_t time_t
Definition: io_binary.c:286
double fn(const gsl_vector *v, void *params)
real(real64) function s()
struct __dirstream DIR
Definition: oct_f.c:4678
long int sysconf(int __name) __attribute__((__nothrow__
void FC_FUNC_(oct_mkdir, OCT_MKDIR)
Definition: oct_f.c:5018
int mkdir(const char *__path, __mode_t __mode) __attribute__((__nothrow__
__pid_t getpid(void)
Definition: oct_f.c:4250
int gettimeofday(struct timeval *__restrict __tv, void *__restrict __tz) __attribute__((__nothrow__
void sysname(char **c)
Definition: varia.c:4623
DIR DIR struct dirent * readdir(DIR *__dirp) __attribute__((__nonnull__(1)))
DIR * opendir(const char *__name) __attribute__((__nonnull__(1))) __attribute__((__malloc__)) __attribute__((__malloc__(closedir
FILE * stderr
int closedir(DIR *__dirp) __attribute__((__nonnull__(1)))
int stat(const char *__restrict __file, struct stat *__restrict __buf) __attribute__((__nothrow__
int fclose(FILE *__stream)
clock_t clock(void)
Definition: oct_f.c:3240
@ _SC_PAGESIZE
Definition: oct_f.c:3681
void progress_bar(int actual, int max)
Definition: varia.c:4741
ptrdiff_t l
Definition: operate_inc.c:12
ptrdiff_t i
Definition: operate_inc.c:12
static double f(double w, void *p)
__mode_t st_mode
Definition: io_binary.c:330
__time_t tv_sec
Definition: getopt_f.c:1115