Skip to content

Commit

Permalink
Add option --include FILE.h to add a #include in the generated C code
Browse files Browse the repository at this point in the history
This option has two side-effect:
* the C file is compiled in the project directory (so that the included file
  can be found locally)
* no prototype is generated, so the new header file must contain a prototype
  for all statically called functions
  • Loading branch information
lefessan committed Oct 13, 2023
1 parent faf6841 commit 3eb9182
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 1 deletion.
8 changes: 8 additions & 0 deletions cobc/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@

2023-10-12 Fabrice Le Fessant <[email protected]>

* cobc.c, codegen.c: new option --include FILE, to #include
additional files in the C generated code. Such files can be
used to statically check the number of arguments in static
calls, for example. The files are put into quoted, unless
they start by '<'

2023-10-11 Fabrice Le Fessant <[email protected]>

* cobc.c, pplex.l: new option --copy COPYBOOK, to include a COPYBOOK
Expand Down
16 changes: 15 additions & 1 deletion cobc/cobc.c
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ enum compile_level {
#define CB_FLAG_GETOPT_DEFAULT_COLSEQ 15
#define CB_FLAG_GETOPT_MEMORY_CHECK 16
#define CB_FLAG_GETOPT_COPY_FILE 17
#define CB_FLAG_GETOPT_INCLUDE_FILE 18


/* Info display limits */
Expand Down Expand Up @@ -234,6 +235,7 @@ const char *demangle_name = NULL;
const char *cb_storage_file_name = NULL;
const char *cb_call_extfh = NULL;
struct cb_text_list *cb_copy_list = NULL;
struct cb_text_list *cb_include_file_list = NULL;
struct cb_text_list *cb_include_list = NULL;
struct cb_text_list *cb_depend_list = NULL;
struct cb_text_list *cb_intrinsic_list = NULL;
Expand Down Expand Up @@ -598,6 +600,7 @@ static const struct option long_options[] = {
{"std", CB_RQ_ARG, NULL, '$'},
{"conf", CB_RQ_ARG, NULL, '&'},
{"copy", CB_RQ_ARG, NULL, CB_FLAG_GETOPT_COPY_FILE},
{"include", CB_RQ_ARG, NULL, CB_FLAG_GETOPT_INCLUDE_FILE},
{"debug", CB_NO_ARG, NULL, 'd'},
{"ext", CB_RQ_ARG, NULL, 'e'}, /* note: kept *undocumented* until GC4, will be changed to '.' */
{"free", CB_NO_ARG, NULL, 'F'}, /* note: not assigned directly as this is only valid for */
Expand Down Expand Up @@ -3898,6 +3901,16 @@ process_command_line (const int argc, char **argv)
break;
}

case CB_FLAG_GETOPT_INCLUDE_FILE: /* 18 */
/* -include=<file.h> : add #include "file.h" to
generated C file */
{
char *file = cobc_strdup (cob_optarg);
cb_flag_c_decl_for_static_call = 0;
CB_TEXT_LIST_ADD (cb_include_file_list, file);
break;
}

case 'A':
/* -A <xx> : Add options to C compile phase */
COBC_ADD_STR (cobc_cflags, " ", cob_optarg, NULL);
Expand Down Expand Up @@ -4445,7 +4458,8 @@ process_filename (const char *filename)
fn->translate = cobc_main_strdup (output_name);
} else
if (save_all_src || save_temps || save_c_src
|| cb_compile_level == CB_LEVEL_TRANSLATE) {
|| cb_include_file_list
|| cb_compile_level == CB_LEVEL_TRANSLATE) {
fn->translate = cobc_main_stradd_dup (fbasename, ".c");
} else {
fn->translate = cobc_main_malloc (COB_FILE_MAX);
Expand Down
1 change: 1 addition & 0 deletions cobc/cobc.h
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,7 @@ extern FILE *cb_src_list_file;
extern FILE *cb_depend_file;
extern struct cb_text_list *cb_depend_list;
extern struct cb_text_list *cb_copy_list;
extern struct cb_text_list *cb_include_file_list;
extern struct cb_text_list *cb_include_list;
extern struct cb_text_list *cb_intrinsic_list;
extern struct cb_text_list *cb_extension_list;
Expand Down
11 changes: 11 additions & 0 deletions cobc/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1833,6 +1833,17 @@ output_gnucobol_defines (const char *formatted_date)
current_compile_tm.tm_sec;
output_line ("#define COB_MODULE_TIME\t\t%d", i);

{
struct cb_text_list *l = cb_include_file_list ;
for (;l;l=l->next){
if (l->text[0] == '<'){
output_line ("#include %s", l->text);
} else {
output_line ("#include \"%s\"", l->text);
}
}
}

}

/* CALL cache */
Expand Down
1 change: 1 addition & 0 deletions cobc/help.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ cobc_print_usage_common_options (void)
puts (_(" -I <directory> add <directory> to copy/include search path"));
puts (_(" --copy <copybook> include <copybook> at beginning of file, as would COPY copybook."));
puts (_(" -L <directory> add <directory> to library search path"));
puts (_(" --include <file.h> add a #include \"file.h\" at the beginning of the C generated file."));
puts (_(" -l <lib> link the library <lib>"));
puts (_(" -K <entry> generate CALL to <entry> as static"));
puts (_(" -D <define> define <define> for COBOL compilation"));
Expand Down
9 changes: 9 additions & 0 deletions doc/gnucobol.texi
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,15 @@ another process. You can manually set an output file using @option{-o}.
Include @file{copybook} at the beginning of the source code, as if
@code{COPY copybook} had been parsed.

@item --include @var{file.h}
Add a @code{#include} @file{file.h} at the beginning of the generated
C source file. The file name is put into quotes, unless it starts by
@code{<}. This option can be used to check function prototypes when
static calls are used. When this option is used, the source file is
compiled in the project directory (instead of the temp directory), and
no prototypes are generated, so ALL static call functions must appear
in the header file, with GnuCOBOL compatible types.

@item -C
Translation only. COBOL source files are translated into C files.
The output is saved in file @file{*.c}.
Expand Down
31 changes: 31 additions & 0 deletions tests/testsuite.src/used_binaries.at
Original file line number Diff line number Diff line change
Expand Up @@ -1002,3 +1002,34 @@ AT_CHECK([$COBC -fdiagnostics-plain-output -fdiagnostics-show-caret -Wno-others

AT_CLEANUP


AT_SETUP([check include header file])
AT_KEYWORDS([-include])

AT_DATA([file.h], [
extern void f(char *, long );
])

AT_DATA([prog.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
PROCEDURE DIVISION.
CALL "f" USING "Hello".
])

# We ignore the error output, as it depends on the C compiler in use
AT_CHECK([$COBC -m --include file.h -fstatic-call prog.cob], [1], [], [ignore])

AT_DATA([prog2.cob], [
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 long USAGE BINARY-C-LONG.
PROCEDURE DIVISION.
CALL "f" USING "Hello" BY VALUE long RETURNING NOTHING.
])

AT_CHECK([$COBC -m --include file.h -fstatic-call prog2.cob], [0], [], [])

AT_CLEANUP

0 comments on commit 3eb9182

Please sign in to comment.