Discussion:
Can C #includes like this be made to work onVMS?
(too old to reply)
Brian Schenkenberger
2024-10-15 18:42:11 UTC
Permalink
I want to port a freeware package. It's C code is littered with includes like:

#include "package_name/include_file.h"

I've tried the DECC$***_INCLUDE logicals, the CC command quilifier
/INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
mjos_examine
2024-10-15 19:08:00 UTC
Permalink
Post by Brian Schenkenberger
#include "package_name/include_file.h"
I've tried the DECC$***_INCLUDE logicals, the CC command quilifier /
INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
$ type test.c
#include <stdio.h>
#include <stdlib.h>
#include "package_name/include_file.h"

int main(int argc, char *argv[])
{
printf("this is a test: %s.\n", testresult);
}


$ type [.package_name]include_file.h
#define testresult "test include file"

$ cc test.c
$

$ show log dec*

(LNM$PROCESS_TABLE)

"DECC$ARGV_PARSE_STYLE" = "ENABLE"
"DECC$EFS_CASE_PRESERVE" = "ENABLE"
"DECC$EFS_CHARSET" = "ENABLE"

$ dir [...]

Directory DKA100:[DEVEL.testincl]

package_name.DIR;1 TEST.C;1 TEST.OBJ;1

Total of 3 files.

Directory DKA100:[DEVEL.testincl.package_name]

INCLUDE_FILE.H;1

Total of 1 file.

Grand total of 2 directories, 4 files.
John Dallman
2024-10-15 19:15:00 UTC
Permalink
Post by Brian Schenkenberger
#include "package_name/include_file.h"
I've tried the DECC$***_INCLUDE logicals, the CC command quilifier
/INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
Don't try to define "package name". General C practice is to regard that
as a directory name that the compiler should look for, used to collect
specific headers together.

Instead, try using the various ways of specifying where you want include
files to be read from to indicate the directory that holds the
"package_name" directory.

The compiler should look for the directory called "package_nane" and the
"include_file.h" within it.

John
Brian Schenkenberger
2024-10-15 19:21:46 UTC
Permalink
Post by John Dallman
Post by Brian Schenkenberger
#include "package_name/include_file.h"
I've tried the DECC$***_INCLUDE logicals, the CC command quilifier
/INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
Don't try to define "package name". General C practice is to regard that
as a directory name that the compiler should look for, used to collect
specific headers together.
Instead, try using the various ways of specifying where you want include
files to be read from to indicate the directory that holds the
"package_name" directory.
The compiler should look for the directory called "package_nane" and the
"include_file.h" within it.
John
In the distribution, the includes are in a directory:

[package_name.INCLUDE]

and the source is in [package_name.SRC]

I am hoping not to have to edit all of the sources to change the
#include "..."s.
mjos_examine
2024-10-15 19:42:04 UTC
Permalink
Post by Brian Schenkenberger
Post by Brian Schenkenberger
#include "package_name/include_file.h"
[...]
Post by Brian Schenkenberger
[package_name.INCLUDE]
and the source is in [package_name.SRC]
I am hoping not to have to edit all of the sources to change the
#include "..."s.
$ create/dir dka100:[my_package_name.include]
$ edit/edt dka100:[my_package_name.include]include_file.h
$ dir dka100:[my_package_name.include]

Directory DKA100:[my_package_name.include]

INCLUDE_FILE.H;1

Total of 1 file.
$ define package_name [my_package_name.include]

$ show def
dka100:[devel.testincl]

$ type dka100:[devel.testincl]test.c
#include <stdio.h>
#include <stdlib.h>
#include "package_name/include_file.h"

int main(int argc, char *argv[])
{
printf("this is a test: %s.\n", testresult);
}

$ cc test.c
$
Arne Vajhøj
2024-10-15 19:54:34 UTC
Permalink
Post by Brian Schenkenberger
Post by John Dallman
Post by Brian Schenkenberger
#include "package_name/include_file.h"
I've tried the DECC$***_INCLUDE logicals, the CC command quilifier
/INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
Don't try to define "package name". General C practice is to regard that
as a directory name that the compiler should look for, used to collect
specific headers together.
Instead, try using the various ways of specifying where you want include
files to be read from to indicate the directory that holds the
"package_name" directory.
The compiler should look for the directory called "package_nane" and the
"include_file.h" within it.
[package_name.INCLUDE]
and the source is in [package_name.SRC]
I am hoping not to have to edit all of the sources to change the
#include "..."s.
$ define package_name [package_name.INCLUDE]

should work.

$ cc/include will not work with this weird setup. If you changed the
includes to be:
#include "include_file.h"
or:
#include "package_name/include/include_file.h" or
then it would work.

Writing some DCL that does an edit/edt/comm with a substitute on
all .c files in a directory tree is not that hard to write. Doing it
in Macro-32 may take a little longer even for you.

:-)

Arne
Arne Vajhøj
2024-10-15 22:50:58 UTC
Permalink
Post by Arne Vajhøj
Post by Brian Schenkenberger
Post by John Dallman
Post by Brian Schenkenberger
#include "package_name/include_file.h"
I've tried the DECC$***_INCLUDE logicals, the CC command quilifier
/INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
Don't try to define "package name". General C practice is to regard that
as a directory name that the compiler should look for, used to collect
specific headers together.
Instead, try using the various ways of specifying where you want include
files to be read from to indicate the directory that holds the
"package_name" directory.
The compiler should look for the directory called "package_nane" and the
"include_file.h" within it.
[package_name.INCLUDE]
and the source is in [package_name.SRC]
I am hoping not to have to edit all of the sources to change the
#include "..."s.
$ define package_name [package_name.INCLUDE]
should work.
$ cc/include will not work with this weird setup. If you changed the
    #include "include_file.h"
    #include "package_name/include/include_file.h" or
then it would work.
Or move the include files to [package_name.INCLUDE.package_name].

Any setup where the include path and file system path match
are OK.

Arne
Arne Vajhøj
2024-10-15 23:48:41 UTC
Permalink
Post by Arne Vajhøj
Writing some DCL that does an edit/edt/comm with a substitute on
all .c files in a directory tree is not that hard to write.
Demo:

$ type z*.c

DKA0:[arne]z1.c;1

#include "a/something.h"

DKA0:[arne]z2.c;1

#include "a/something.h"

DKA0:[arne]z3.c;1

#include "a/something.h"
$ type ab.com
$ loop:
$ fnm = f$search("z*.c")
$ if fnm .eqs. "" then goto endloop
$ define/user sys$input sys$command
$ edit/edt/comm=ab.edt 'fnm'
$ goto loop
$ endloop:
$ exit
$ type ab.edt
s\#include "a/\#include "b/\w
ex
$ @ab
...
$ type z*.c

DKA0:[arne]z1.c;2

#include "b/something.h"

DKA0:[arne]z2.c;2

#include "b/something.h"

DKA0:[arne]z3.c;2

#include "b/something.h"
$ type bc.com
$ loop:
$ fnm = f$search("z*.c")
$ if fnm .eqs. "" then goto endloop
$ define/user sys$input sys$command
$ edit/tpu/init=bc.eve 'fnm'
$ goto loop
$ endloop:
$ exit
$ type bc.eve
all replace "#include ""b/" "#include ""c/"
exit
$ @bc
...
$ type z*.c

DKA0:[arne]z1.c;3

#include "c/something.h"

DKA0:[arne]z2.c;3

#include "c/something.h"

DKA0:[arne]z3.c;3

#include "c/something.h"
$ type cd.com
$ loop:
$ fnm = f$search("z*.c")
$ if fnm .eqs. "" then goto endloop
$ define/user sys$input sys$command
$ edit/tpu/comm=cd.tpu 'fnm'
$ goto loop
$ endloop:
$ exit
$ type cd.tpu
eve_all_replace("#include ""c/", "#include ""d/");
eve_exit();
$ @cd
...
$ type z*.c

DKA0:[arne]z1.c;4

#include "d/something.h"

DKA0:[arne]z2.c;4

#include "d/something.h"

DKA0:[arne]z3.c;4

#include "d/something.h"

Arne

PS: Yes - both gawk and Perl can probably do it in way fewer lines.
Arne Vajhøj
2024-10-16 22:44:44 UTC
Permalink
Post by Arne Vajhøj
$ type bc.eve
all replace "#include ""b/" "#include ""c/"
exit
$ type cd.tpu
eve_all_replace("#include ""c/", "#include ""d/");
eve_exit();
Just realized that one is custom not standard.

!
! Replace all occurences of string with another string (without
! confirm).
!
! High-level.
!
procedure eve_all_replace(fndstr,rplstr)
local fnd_string,
rpl_string,
pos_mark,
count_integer;
if not (eve$prompt_string(fndstr,fnd_string,"Old string: ",
"No old string given")) then
return;
endif;
if not (eve$prompt_string(rplstr,rpl_string,"New string ",
"No new string given")) then
return;
endif;
pos_mark:=mark(none);
set (screen_update, off);
eve$all_replace(fnd_string,rpl_string,count_integer);
position (pos_mark);
set (screen_update, on);
delete (pos_mark);
message("Total of "+str(count_integer)+" replaces");
endprocedure;
!
! Replace all occurences of string with another string (without
! confirm).
!
! Low-level.
!
procedure eve$all_replace(fndstr,rplstr,count)
local find_mark;
position (beginning_of(current_buffer));
count:=0;
loop
find_mark:=search_quietly(fndstr, forward);
exitif find_mark = 0;
count:=count+1;
position (find_mark);
copy_text (rplstr);
erase_character (length(fndstr));
endloop;
endprocedure;

Arne
Lawrence D'Oliveiro
2024-10-16 23:00:14 UTC
Permalink
Post by Arne Vajhøj
procedure eve_all_replace(fndstr,rplstr)
local fnd_string,
rpl_string, pos_mark, count_integer;
if not (eve$prompt_string(fndstr,fnd_string,"Old string: ",
"No old string given")) then
return;
When DEC introduced TPU/EVE, I raised my arms to the heavens in joy at
finally being liberated from the suffering that was EDT. (Hate EDT. Hate,
hate, hate.)

Then I left it behind with VMS ... and a few decades later, finally found
the time to get to grips with Emacs.

In Emacs/ELisp, there is the distinction between a “function” (what TPU
would call a “procedure”, I guess) and a “command”. A “function” only
becomes a “command” when you insert the “(interactive ...)” directive near
its start. This is a declarative construct that supplies the information
Emacs uses to obtain the right arguments for the function automatically,
including prompting the user as necessary, so your code doesn’t have to.
Arne Vajhøj
2024-10-16 23:26:52 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Arne Vajhøj
procedure eve_all_replace(fndstr,rplstr)
local fnd_string,
rpl_string, pos_mark, count_integer;
if not (eve$prompt_string(fndstr,fnd_string,"Old string: ",
"No old string given")) then
return;
When DEC introduced TPU/EVE, I raised my arms to the heavens in joy at
finally being liberated from the suffering that was EDT. (Hate EDT. Hate,
hate, hate.)
Then I left it behind with VMS ... and a few decades later, finally found
the time to get to grips with Emacs.
In Emacs/ELisp, there is the distinction between a “function” (what TPU
would call a “procedure”, I guess) and a “command”. A “function” only
becomes a “command” when you insert the “(interactive ...)” directive near
its start. This is a declarative construct that supplies the information
Emacs uses to obtain the right arguments for the function automatically,
including prompting the user as necessary, so your code doesn’t have to.
In EVE a procedure EVE_FOOBAR can be called with:
* command FOOBAR ARG ! the EVE_ prefix makes it a command
* command TPU EVE_FOOBAR(ARG) ! only interesting if it does not have the
EVE_ prefix

Arne
Lawrence D'Oliveiro
2024-10-16 23:38:23 UTC
Permalink
Post by Arne Vajhøj
* command FOOBAR ARG ! the EVE_ prefix makes it a command
But you still had to call eve$prompt_string and all that jazz.
Arne Vajhøj
2024-10-17 00:11:15 UTC
Permalink
Post by Lawrence D'Oliveiro
Post by Arne Vajhøj
* command FOOBAR ARG ! the EVE_ prefix makes it a command
But you still had to call eve$prompt_string and all that jazz.
TPU is a procedural language.

eve_all_replace calls eve$prompt_string and eve$all_replace.

But that has not really anything to do with the command.

command ALL REPLACE "A" "B"

execute:

EVE_ALL_REPLACE("A", "B");

and the command execution does not care whether all code
in EVE_ALL_REPLACE is inline or in separate procedures.

Arne
Lawrence D'Oliveiro
2024-10-17 01:14:06 UTC
Permalink
Post by Arne Vajhøj
Post by Lawrence D'Oliveiro
Post by Arne Vajhøj
* command FOOBAR ARG ! the EVE_ prefix makes it a command
But you still had to call eve$prompt_string and all that jazz.
TPU is a procedural language.
So is ELisp. But it has a declarative mechanism to allow custom functions
to hook easily into the standard editor framework. This includes the UI.
Arne Vajhøj
2024-10-16 23:28:44 UTC
Permalink
Post by Lawrence D'Oliveiro
When DEC introduced TPU/EVE, I raised my arms to the heavens in joy at
finally being liberated from the suffering that was EDT. (Hate EDT. Hate,
hate, hate.)
I definitely prefer EVE over EDT.

But there are a few reasons to use EDT:
* it uses less memory
* it has line mode

Arne
Craig A. Berry
2024-10-17 01:34:49 UTC
Permalink
Post by Arne Vajhøj
Post by Arne Vajhøj
$ type bc.eve
all replace "#include ""b/" "#include ""c/"
exit
$ type cd.tpu
eve_all_replace("#include ""c/", "#include ""d/");
eve_exit();
Just realized that one is custom not standard.
!
!  Replace all occurences of string with another string (without
!  confirm).
!
!  High-level.
!
procedure eve_all_replace(fndstr,rplstr)
local fnd_string,
      rpl_string,
      pos_mark,
      count_integer;
if not (eve$prompt_string(fndstr,fnd_string,"Old string: ",
                          "No old string given")) then
    return;
endif;
if not (eve$prompt_string(rplstr,rpl_string,"New string ",
                          "No new string given")) then
    return;
endif;
pos_mark:=mark(none);
set (screen_update, off);
eve$all_replace(fnd_string,rpl_string,count_integer);
position (pos_mark);
set (screen_update, on);
delete (pos_mark);
message("Total of "+str(count_integer)+" replaces");
endprocedure;
!
!  Replace all occurences of string with another string (without
!  confirm).
!
!  Low-level.
!
procedure eve$all_replace(fndstr,rplstr,count)
local find_mark;
position (beginning_of(current_buffer));
count:=0;
loop
    find_mark:=search_quietly(fndstr, forward);
    exitif find_mark = 0;
    count:=count+1;
    position (find_mark);
    copy_text (rplstr);
    erase_character (length(fndstr));
endloop;
endprocedure;
eve_all_replace may be custom, but as far as I know eve_global_replace
is standard. Here's an example of using TPU as a poor man's Perl:

$ edit/tpu/nodisplay/noinitialization -
/section=sys$library:eve$section.tpu$section -
/command=sys$input/output=myfile.txt myfile.txt
input_file := GET_INFO (COMMAND_LINE, "file_name");
main_buffer:= CREATE_BUFFER ("main", input_file);
POSITION (BEGINNING_OF (main_buffer));
eve_global_replace("foo","bar");
out_file := GET_INFO (COMMAND_LINE, "output_file");
WRITE_FILE (main_buffer, out_file);
quit;
^Z

But yeah, Perl is way easier:

$ perl -pi -e "s/foo/bar/g;" myfile.txt
Arne Vajhøj
2024-10-17 02:13:56 UTC
Permalink
Post by Craig A. Berry
Post by Arne Vajhøj
Post by Arne Vajhøj
$ type bc.eve
all replace "#include ""b/" "#include ""c/"
exit
$ type cd.tpu
eve_all_replace("#include ""c/", "#include ""d/");
eve_exit();
Just realized that one is custom not standard.
procedure eve_all_replace(fndstr,rplstr)
eve_all_replace may be custom, but as far as I know eve_global_replace
is standard.
Yes - it is.

I wonder why I have that eve_all_replace.
Post by Craig A. Berry
$ edit/tpu/nodisplay/noinitialization -
    /section=sys$library:eve$section.tpu$section -
    /command=sys$input/output=myfile.txt myfile.txt
input_file := GET_INFO (COMMAND_LINE, "file_name");
main_buffer:= CREATE_BUFFER ("main", input_file);
POSITION (BEGINNING_OF (main_buffer));
eve_global_replace("foo","bar");
out_file := GET_INFO (COMMAND_LINE, "output_file");
WRITE_FILE (main_buffer, out_file);
quit;
^Z
$ perl -pi -e "s/foo/bar/g;" myfile.txt
Of course.

:-)

Arne
Arne Vajhøj
2024-10-18 13:36:18 UTC
Permalink
Post by Arne Vajhøj
Post by Craig A. Berry
Post by Arne Vajhøj
Post by Arne Vajhøj
$ type bc.eve
all replace "#include ""b/" "#include ""c/"
exit
$ type cd.tpu
eve_all_replace("#include ""c/", "#include ""d/");
eve_exit();
Just realized that one is custom not standard.
procedure eve_all_replace(fndstr,rplstr)
eve_all_replace may be custom, but as far as I know eve_global_replace
is standard.
Yes - it is.
I wonder why I have that eve_all_replace.
There are a small difference in prompt behavior (all replace does
not prompt if I want to go to start and repeat). But that is
pretty subtle. The implementation is very different. eve_global_replace
calls eve_replace with a global variable set to change its behavior.

Maybe eve_global_replace was added with the major EVE rewrite in 5.0
and I kept eve_all_replace when I rewrote from 4.x to 5.x.

Anybody that has a VMS 4.x system and could do:

$ sear sys$examples:eve$edit.tpu eve_global_replace

?

Arne

Craig A. Berry
2024-10-16 00:35:55 UTC
Permalink
Post by Brian Schenkenberger
[package_name.INCLUDE]
and the source is in [package_name.SRC]
I am hoping not to have to edit all of the sources to change the
#include "..."s.
Is there possibly a configuration step that copies package_name/include/
up to package_name/ in preparation for a build?
Mark Berryman
2024-10-16 06:35:39 UTC
Permalink
Post by Brian Schenkenberger
Post by John Dallman
Post by Brian Schenkenberger
#include "package_name/include_file.h"
I've tried the DECC$***_INCLUDE logicals, the CC command quilifier
/INCLUDE_DIRECTORY and logicals, rooted and otherwise, defining
"package_name". Can't get the C compiler to find include_file.h.
Don't try to define "package name". General C practice is to regard that
as a directory name that the compiler should look for, used to collect
specific headers together.
Instead, try using the various ways of specifying where you want include
files to be read from to indicate the directory that holds the
"package_name" directory.
The compiler should look for the directory called "package_nane" and the
"include_file.h" within it.
John
[package_name.INCLUDE]
and the source is in [package_name.SRC]
I am hoping not to have to edit all of the sources to change the
#include "..."s.
Given what you have described, there are at least two ways to address this.

1. By far the easiest is to $define package_name [package_name.include]
which will use the normal C RTL rules for finding files.

2. As an alternative, the following will also work.

a. create/dir [package_name.include.package_name]
and move all of the include files into that directory
b. create first.h
#pragma include_directory "./package_name/include"
^Z
c. Do your compiles from the top_level directory
CC/FIRST=first.h [.src]file.c

I find it easiest to create a descrip.mms file to do this and let mms do
the work.

Mark Berryman
Loading...