Is there a way to rename a file in fortran 77? such as:
RENAME(old name, new name)
or something like:
call system("rename" // trim(old name) // " " // trim(new name))
Thanks
I think you nailed it with the first one:
CALL RENAME('oldname','newname')
More here. And here.
You can use the modFileSys library for that. In contrast to non-standard compiler extensions, it can be compiled with any Fortran 2003 compiler and can be used an all POSIX compatible systems. You could also check for errors, if needed:
program test
use libmodfilesys_module
implicit none
integer :: error
! Renaming with error handling
call rename("old.dat", "new.dat", error=error)
if (error /= 0) then
print *, "Error happened"
end if
! Renaming without explicit error handling, stops the program
! if error happens.
call rename("old2.dat", "new2.dat")
end program test
Related
Is there an alternative to the err() family of functions found in <err.h> that displays the program name, a semicolon, a space, and the error message... without exiting the program?
Pseudocode
I want
print "<program name>: <error message>"
and not
print "<program name>: <error message>"
exit program
return <status>
EDIT: I cannot use argv[0] (as the program name) to write out the message myself, as I am writing a library
program_invocation_name works just as well for getting the name of the program, as Erdal Küçük mentioned. From this, we can print the full error message, program name included.
The variable is part of glibc and can be retrieved using:
extern char *program_invocation_name;
Because it is not a part of the C standard library, programs using this variable should not be expected to be portable.
See man error.
error is the same as err but will return if status == 0, exit otherwise.
CONFORMING TO
These functions and variables are GNU extensions, and should not be used in programs intended to be portable.
The warn/warnx functions from err.h will do the same thing as err, but will return.
For example:
warnx("message here");
puts("I'm still running!");
Output:
a.out: message here
I'm still running!
I've been messing around with Idris lately and decided to try playing around with its Network.Socket library. I fired up the REPL, imported the module, and created a socket using the socket command. Upon attempting to execute the IO operation, I was met with the following error:
failed to construct ffun from (Builtins.MkPair (FFI_C.C_Types (Int)) (Int) (FFI_C.C_IntT (Int) (FFI_C.C_IntNative)) (2),Builtins.MkPair (FFI_C.C_Types (Int)) (Int) (FFI_C.C_IntT (Int) (FFI_C.C_IntNative)) (1),[])
Symbol "socket" not found
user error (Could not call foreign function "socket" with args [2,1,0])
To see whether the issue was Network.Socket specific, or just FFI in general, I made a dummy function.
printf : String -> IO ()
printf = foreign FFI_C "printf" (String -> IO ())
Executed :x printf "Hello World" yields a similar error:
Symbol "printf" not found
user error (Could not call foreign function "printf" with args ["hello world"])
Despite all this, putStr works fine.
I am running Idris 9.20, installed through cabal with -f FFI set at compile. I am using libffi version 3.4 installed through MacPorts.
I believe that this has to do with the fact that the Idris FFI operates differently depending on whether code is being compiled or interpreted. When code is being compiled, the FFI requires that at the stage of C codegen, the named C function be in scope, and that when linking the C executable, the correct name is linked in. Since Idris's RTS links against libc, this makes a lot of names from libc work without any extra effort (certain names might require a %include to make sure that the correct C header file is included to put them in scope). When code is being interpreted, the interpreter looks up FFI calls in a list of libraries that have been loaded dynamically, which requires a different directive: %dynamic in the file, or :dynamic in the interpreter. By default, no dynamic libraries are loaded, so even standard names in libc are not in scope. This can be remedied by including %dynamic "libc" in the file, or using the :dynamic "libc" at the REPL commandline for one session.
I'm trying to call a C shared library function from LibreOffice Basic, but I always get "Basic Runtime Error. Not implemented" when it hits the Declare line. It's just for a fun thing but being unable to do it is bugging me.
The Declare statement looks like this:
Declare Function score_word Lib "libscrabblescore.so" (ByRef word As String, ByRef bonus As String) As Integer
The C function delaration looks like this:
int score_word(char* word, char* word_bonuses)
(Maybe ByRef word As String is not the right translation of char* word? I can't find documentation on how to use char* parameters to functions from LibreOffice Basic.)
I validated the shared library itself by calling it using Python's ctypes module:
>>> from ctypes import CDLL
>>> lib = CDLL("/usr/lib/libscrabblescore.so")
>>> lib.score_word("qi", "dw dlq")
42
>>>
(So I have the "Answer to the Ultimate Question of Life, the Universe, and Everything," just not for how to do this in LibreOffice Basic!)
I tried using the absolute path in the Declare statement as well, and it made no difference.
I found a Windows thread on the topic of calling DLL's where the asker said he needed to put the DLL in a specific location (the LibreOffice bin directory) so LibreOffice could access it. There is no LibreOffice bin directory per-se on Linux, and unfortunately there are 351 candidate directories I was able to identify on my machine (my path, and all folders with "libreoffice" in the name or under a folder with "libreoffice" in the name).
I tried a shotgun approach and put a symbolic link to the shared library in all 351 directories, but then Calc hangs on startup. So I removed those, started Calc, and put them all back in place and tried the function. If it was a location thing, you'd think that would work as LibreOffice Basic is supposed to load the library at the point of the Declare. Still no luck.
There was something that looked promising on oooforums but the site times out when I try to view the thread. (EDIT: I managed to view the thread this evening and it was Windows security problem. I turned off all macro security in my LibreOffice and still have the problem.)
So, has anybody ever successfully called a C shared library function from a LibreOffice Basic program that knows what I'm doing wrong? Thanks!
Jonathon Reinhart is correct; the "Declare" command for calling shared libraries is implemented on Windows but not on Linux. I was only able to verify this because of a reference to an OpenOffice bug report on the matter on a blog post.
My first attempt at a solution was to rewrite the function in LibreOffice Basic. It worked, but would take up to 3 seconds to return its results.
I considered giving up and leaving it like that, but it was too unpleasant to have a three second wait. I looked into how to implement a C++ function through UNO, which was overly complex for a fairly trivial task.
Finally what I did was to write a kludge that still gives "instant" results (around 0.025 seconds each function call).
I rewrote the DLL as a C++ console app that takes command line arguments and writes the result to a temp file. Then I replaced my LibreOffice Basic code with a function that calls the C++ console app in blocking mode using Shell and retrieves the results from the file. It's ugly, but it's not a multi-user thing and it works.
In case anyone stumbles across this issue themselves, here's the LibreOffice Basic code I used to do this--it's very simple.
option explicit
function scorewords(wordlist as string, bonuslist as string) as integer
dim cparams as string
dim fileno as integer
dim results_file as string
dim score as integer
if wordlist = "" then
scorewords = 0
exit function
end if
cparams = """" + wordlist + """" + " " + """" + bonuslist + """"
results_file = "/tmp/scrabblescore.dat"
Shell("/usr/bin/getscrabblescore", 6, cparams, true)
fileno = freefile
open results_file for input as fileno
input #fileno, score
close #fileno
kill results_file
scorewords = score
end function
Unless you are limited to Basic then it looks like your question already shows a good solution. Write something like this in Python UNO:
import ctypes
lib = ctypes.cdll.loadLibrary("/usr/lib/libscrabblescore.so")
result = lib.score_word("qi", "dw dlq")
oText.insertString(oTextCursor, result, 0)
I am running a Ruby gem which relies on a C extension (not a call to system).
The C code makes several calls to printf.
I want to silence the output of these calls.
Changing Ruby's STDOUT (example) or STDERR does not prevent the text from being output.
Is it possible to do this without modifying the C code? If so, how?
Someone originally commented on my post suggesting to use IO.reopen. This worked for me. The person has unfortunately since deleted his/her comment, so I'm posting the more detailed function I used in the end:
def silence_stdout(log = '/dev/null')
old = $stdout.dup
$stdout.reopen(File.new(log, 'w'))
yield
$stdout = old
end
Usage:
silence_stdout { foo } # Won't be displayed, won't be logged.
silence_stdout('log.txt') { bar } # Won't be displayed, logged in log.txt.
It is possible that Ruby is printing to stderr instead of stdout, which is why changing Ruby's stdout doesn't fix your problem.
(Both stderr and stdout typically go to the console.)
Try redirecting stderr. As I recall it'd be: myprogram 2> /dev/null
If you have access to the C source code:
#define printf(...)
This macro form is a C99 variadic macro.
I’m trying to initialize the Metal C environment with the following code, but get the following errors on the memset line.
ERROR CCN3275 IMIJWS0.METAL.SAMPLIB(MEM):6 Unexpected text ')' encountered.
ERROR CCN3045 IMIJWS0.METAL.SAMPLIB(MEM):6 Undeclared identifier ___MEMSET.
ERROR CCN3277 IMIJWS0.METAL.SAMPLIB(MEM):6 Syntax error: possible missing ')' or ','?
CCN0793(I) Compilation failed for file //'IMIJWS0.METAL.SAMPLIB(MEM)'. Object file not created.
Below is my code
#include < string.h>
#include < stdlib.h>
#include < metal.h>
void mymtlfcn(void) {
struct __csysenv_s mysysenv;
memset ( &mysysenv, 0, sizeof ( mysysenv ) );
mysysenv.__cseversion = __CSE_VERSION_1;
mysysenv.__csesubpool = 129;
mysysenv.__cseheap31initsize = 131072;
mysysenv.__cseheap31incrsize = 8192;
mysysenv.__cseheap64initsize = 20;
mysysenv.__cseheap64incrsize = 1;
The issue was with the search order. Although I did search(/usr/metal/include) from with in my JCL I didn't proceed it with a nosearch option, so string.h was getting picked up from the standard system librarys instead of the version included with Metal C. I've pasted my optfile dataset I passed to the CPARM below for refference.
//OPTIONS DD *
SO
LIST
LONG
NOXREF
CSECT
METAL
LP64
NOSEARCH
search(/usr/include/metal/)
So, I have no idea. But some suggestions:
You might try copying/pasting this code here from this example just to make sure it works 'as expected'
Maybe try defining some of the macros here? (when I did C programming on zOS, I had to do include some weird macros in order to get stuff to work. I have no reasonable technical explanation for this.)
You could try searching for memset() using "=3.14" (from ispf.) See if any other modules use that function, and then check the headers that they include (or macros that they define - either in the C files or H files) to make it work.
Another thought: before the memset(), try doing putting a printf() in. If you get a syntax error on the same line (only for printf, rather than memset) then you can see if the problem is before line 6 - like a misplaced parenthesis.
Finally, if i recall correctly, I had to compile my individual modules, and then link them manually (unless I wrote a JCL to do this for me.) So you might have to link once to link with your other modules, and then link again against the C library. Not to be pedantic, but: you're fairly certain that you're doing all of the link passes?
I realize that's a lot of hoops to try and you've probably already read the manuals, but maybe there is something useful to try?
Also, and you probably already know this, but this site (for looking up error codes) is infinitely useful. (along with the above links for full-text-searching the manual)
Edit: this page also talks about "built-in functions" - you could try (as stated at the bottom of the page) "#undef memcpy" to use the non-built-in version?
Can you show us your compiler arguments? You need to make sure that you're not pulling in the standard C header files in addition to the metal C ones. Here's an example:
xlc -c -Wc,metal,longname,nosearch,'list(./)' -I. -I /usr/include/metal -I "//'SYS1.SIEAHDRV'" -S -qlanglvl=extended foo.c
as -mrent -mgoff -a=foo.list -o foo.o foo.s
ld -bac=1 -brent -S "//'SYS1.CSSLIB'" -o foo foo.o
Are you missing the closing brace '}' for the function? How about any missing semi-colon line terminators? When missing braces/semi-colons the z/OS C compiler throws some strange/misleading messages sometimes. I don't have it to try out, but I'm assuming Metal does as well.