Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add >>IMP INCLUDE directive #143

Open
wants to merge 11 commits into
base: gcos4gnucobol-3.x
Choose a base branch
from
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ NEWS - user visible changes -*- outline -*-
calls to externals. The files are put into quotes, unless they start by
'<'. Quoted files are expected to have absolute paths, as the C compiler
is called in a temp directory instead of the project directory.
The directive >>IMP INCLUDE "file.h", >>IMP INCLUDE "<file.h>",
>>IMP INCLUDE <file.h> or >>IMP INCLUDE file.h can be used as an alternative
to this compiler option.

** output of unlimited errors may be requested by -fmax-errors=0,
to stop compiliation at first error use -Wfatal-errors
Expand Down
12 changes: 12 additions & 0 deletions cobc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
compiler aborts on broken expressions, bugs #933, #938 and #966
* typeck.c: minor refactoring within functions

2024-04-25 Boris Eng <boris.eng@ocamlpro.com>

* cobc.h, pplex.l, ppparse.y: new >>IMP INCLUDE directive to include
multiple header files in the C generated code. Has the same behavior as the
--include compiler option.

2024-04-24 Fabrice Le Fessant <fabrice.le_fessant@ocamlpro.com>

* replace.c: optimize speed and memory usage. For speed, we add two
Expand All @@ -38,6 +44,12 @@
replace stream) and we use a circular buffer for the temporary
queue of tokens instead of a list.

2024-04-25 Boris Eng <boris.eng@ocamlpro.com>

* pplex.l, ppparse.y, scanner.l, cobc.h, codegen.c:
new >>IMP INCLUDE directive to include one or multiple header files in
the generated C code (same behavior as the --include compiler option)

engboris marked this conversation as resolved.
Show resolved Hide resolved
2024-03-17 Fabrice Le Fessant <fabrice.le_fessant@ocamlpro.com>
Emilien Lemaire <emilien.lemaire@ocamlpro.com>

Expand Down
3 changes: 2 additions & 1 deletion cobc/cobc.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ enum cb_sub_check {
struct cb_text_list {
struct cb_text_list *next; /* next pointer */
struct cb_text_list *last;
const char *text;
char *text;
};

/* Structure for extended filenames */
Expand Down Expand Up @@ -477,6 +477,7 @@ 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_include_file_list_directive;
engboris marked this conversation as resolved.
Show resolved Hide resolved
extern struct cb_text_list *cb_intrinsic_list;
extern struct cb_text_list *cb_extension_list;
extern struct cb_text_list *cb_static_call_list;
Expand Down
21 changes: 17 additions & 4 deletions cobc/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1830,16 +1830,29 @@ output_gnucobol_defines (const char *formatted_date)
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] == '<'){
struct cb_text_list *l;
struct cb_text_list *last = NULL;
for (l = cb_include_file_list; l; l = l->next) {
if (l->text[0] == '<') {
output_line ("#include %s", l->text);
} else {
output_line ("#include \"%s\"", l->text);
}
}
}

for (l = cb_include_file_list_directive; l; l = l->next) {
if (last != NULL) {
cobc_free (last->text);
cobc_free (last);
}
last = l;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the memory was allocated with cobc_malloc and would need to be always freed, and that must also be done when there is no codegen (preprocess/syntaxy-check only) so must be done outside of codegen.

I think the parse_ memory functions would be more reasonable and drop the need to execute the free, also removing the need to keep the "last" element here; the only thing missing then is to initialize cb_include_file_list_directive at the right place

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, I should free those variables outside/independently of codegen but still after the running of codegen? Maybe after ylex_clear_all () in cobc.c and add a parse_clear_all () function or something like that?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The thought was to drop all the explicit cobc_free calls and move this to "parser memory" using cobc_parse_malloc instead for the allocation; then, potentially at ylex_clear_all or clear_local_codegen_vars unset the var...

Can you please check if this works?

Note: you currently allocate cb_include_file_list_directive with cobc_parse_strdup - so it is parser allocated already and will automatically be freed - you may only need to drop setting the "last" attribute (or create a separate structure) and the free calls here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you may only need to drop setting the "last" attribute (or create a separate structure) and the free calls here.

Looks like it works with that with no leak from valgrind. I didn't unset any variable (tell me if it is necessary).

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

/* CALL cache */
Expand Down
16 changes: 16 additions & 0 deletions cobc/pplex.l
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ ALNUM_LITERAL_A "\'"([^''\n]|("\'"[0-9][0-9, ]+"\'"))*"\'"
ALNUM_LITERAL {ALNUM_LITERAL_Q}|{ALNUM_LITERAL_A}
SET_PAREN_LIT \([^()\n]*\)
DEFNUM_LITERAL [+-]?[0-9]*[\.]*[0-9]+
RAW_SEQ [^ \n]+
engboris marked this conversation as resolved.
Show resolved Hide resolved

AREA_A [ ]?#
MAYBE_AREA_A [ ]?#?
Expand All @@ -227,6 +228,7 @@ MAYBE_AREA_A [ ]?#?
%x ALNUM_LITERAL_STATE
%x CONTROL_STATEMENT_STATE
%x DISPLAY_DIRECTIVE_STATE
%x IMP_DIRECTIVE_STATE

%%

Expand Down Expand Up @@ -360,6 +362,11 @@ MAYBE_AREA_A [ ]?#?
return CALL_DIRECTIVE;
}

^{MAYBE_AREA_A}[ ]*">>"[ ]?"IMP" {
BEGIN IMP_DIRECTIVE_STATE;
return IMP_DIRECTIVE;
}

^{MAYBE_AREA_A}[ ]*">>"[ ]*\n {
/* empty 2002+ style directive */
cb_plex_warning (COBC_WARN_FILLER, newline_count,
Expand Down Expand Up @@ -724,6 +731,7 @@ ELSE_DIRECTIVE_STATE,
ENDIF_DIRECTIVE_STATE,
ALNUM_LITERAL_STATE,
CONTROL_STATEMENT_STATE,
IMP_DIRECTIVE_STATE,
COBOL_WORDS_DIRECTIVE_STATE>{
\n {
BEGIN INITIAL;
Expand Down Expand Up @@ -993,6 +1001,14 @@ ENDIF_DIRECTIVE_STATE>{
}
}

<IMP_DIRECTIVE_STATE>{
"INCLUDE" { return INCLUDE; } /* GnuCOBOL 3.3 extension */
{RAW_SEQ} {
pplval.s = cobc_plex_strdup (yytext);
return TOKEN;
}
}

<IF_DIRECTIVE_STATE>{
"IS" { return IS; }
"NOT" { return NOT; }
Expand Down
28 changes: 28 additions & 0 deletions cobc/ppparse.y
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,9 @@ ppparse_clear_vars (const struct cb_define_struct *p)
%token WITH
%token LOCATION

%token IMP_DIRECTIVE
%token INCLUDE

%token TERMINATOR "end of line"

%token <s> TOKEN "Word or Literal"
Expand Down Expand Up @@ -768,6 +771,7 @@ ppparse_clear_vars (const struct cb_define_struct *p)
%type <l> alnum_equality_list
%type <l> ec_list
%type <s> unquoted_literal
%type <l> imp_include_sources

%type <r> _copy_replacing
%type <r> replacing_list
Expand Down Expand Up @@ -838,6 +842,7 @@ directive:
| TURN_DIRECTIVE turn_directive
| LISTING_DIRECTIVE listing_directive
| LEAP_SECOND_DIRECTIVE leap_second_directive
| IMP_DIRECTIVE imp_directive
| IF_DIRECTIVE
{
current_cmd = PLEX_ACT_IF;
Expand Down Expand Up @@ -1368,6 +1373,29 @@ leap_second_directive:
| OFF
;

imp_directive:
/* GnuCOBOL 3.3 extension */
INCLUDE imp_include_sources
{
struct cb_text_list *p = $2;
while (p != NULL) {
fprintf (ppout, "#INCLUDE %s\n", p->text);
p = p->next;
}
}
;
engboris marked this conversation as resolved.
Show resolved Hide resolved

imp_include_sources:
TOKEN
{
$$ = ppp_list_add (NULL, fix_filename ($1));
}
| imp_include_sources TOKEN
{
$$ = ppp_list_add ($1, fix_filename ($2));
}
;

turn_directive:
ec_list CHECKING on_or_off
{
Expand Down
26 changes: 26 additions & 0 deletions cobc/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ static size_t pic2_size;
static unsigned int inside_bracket = 0;
static char err_msg[COB_MINI_BUFF];

struct cb_text_list *cb_include_file_list_directive = NULL;

/* Function declarations */
static void read_literal (const char, const enum cb_literal_type);
static int scan_x (const char *, const char *);
Expand All @@ -192,6 +194,7 @@ static void copy_two_words_in_quotes (char ** const, char ** const);
static void add_synonym (const int, const int);
static void make_synonym (void);
static void clear_constants (void);
static struct cb_text_list *scan_list_add (struct cb_text_list *, const char *);

%}

Expand Down Expand Up @@ -323,6 +326,13 @@ AREA_A "#AREA_A"\n
cobc_areacheck = 0;
}

<*>^[ ]?"#INCLUDE".*/\n {
engboris marked this conversation as resolved.
Show resolved Hide resolved
cb_include_file_list_directive = scan_list_add (
cb_include_file_list_directive,
yytext + 9
);
}

<*>^{AREA_A}[ ]*/"." {
count_lines (yytext + 9); /* skip "\n#area_a\n" */
if (cobc_in_procedure && cobc_areacheck) {
Expand Down Expand Up @@ -2583,6 +2593,22 @@ clear_constants (void)
top_78_ptr = NULL;
}

static struct cb_text_list *
scan_list_add (struct cb_text_list *list, const char *text)
{
struct cb_text_list *p;

p = cobc_malloc (sizeof (struct cb_text_list));
p->text = cobc_strdup (text);
engboris marked this conversation as resolved.
Show resolved Hide resolved
if (!list) {
p->last = p;
return p;
}
list->last->next = p;
list->last = p;
return list;
}

/* Global functions */

void
Expand Down
2 changes: 2 additions & 0 deletions doc/gnucobol.texi
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ 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{<}. Quoted files should be absolute paths, since C files are compiled
in temporary directories.
The directive @code{>>IMP INCLUDE "FILE.h"} or @code{>>IMP INCLUDE <FILE.h>}
can be used as an alternative to this compiler option.
The option also implies @option{-fno-gen-c-decl-static-call}.
This option can be used to check function prototypes when
static calls are used. When this option is used, the source file is
Expand Down
64 changes: 64 additions & 0 deletions tests/testsuite.src/syn_misc.at
Original file line number Diff line number Diff line change
Expand Up @@ -8405,3 +8405,67 @@ prog.cob:18: error: ANY LENGTH items may only be BY REFERENCE formal parameters

AT_CLEANUP


AT_SETUP([IMP INCLUDE directive])
engboris marked this conversation as resolved.
Show resolved Hide resolved
AT_KEYWORDS([IMP INCLUDE])

AT_DATA([prog.cob], [
>>IMP INCLUDE "file.h"
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
PROCEDURE DIVISION.
GOBACK.
])

AT_CHECK([$COMPILE_ONLY -fformat=fixed prog.cob], [0], [], [])

AT_DATA([prog.cob], [
>>IMP INCLUDE "file.h"
identification division.
program-id. prog.
procedure division.
goback.
])

AT_CHECK([$COMPILE_ONLY -fformat=free prog.cob], [0], [], [])

AT_DATA([prog.cob], [
>>IMP INCLUDE <file.h>
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
PROCEDURE DIVISION.
GOBACK.
])

AT_CHECK([$COMPILE_ONLY -fformat=fixed prog.cob], [0], [], [])

AT_DATA([prog.cob], [
>>IMP INCLUDE
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
PROCEDURE DIVISION.
GOBACK.
])

AT_CHECK([$COMPILE_ONLY -fformat=fixed prog.cob], [1], [],
engboris marked this conversation as resolved.
Show resolved Hide resolved
[prog.cob:2: error: syntax error, unexpected end of line, expecting Word or Literal
prog.cob:2: error: PROGRAM-ID header missing
])

AT_CLEANUP


AT_SETUP([IMP INCLUDE directive multiple files])
AT_KEYWORDS([IMP INCLUDE])

AT_DATA([prog.cob], [
>>IMP INCLUDE "file1.h" file2.h <file3.h> "<file4.h>"
identification division.
program-id. prog.
procedure division.
goback.
])
engboris marked this conversation as resolved.
Show resolved Hide resolved

AT_CHECK([$COMPILE_ONLY -fformat=free prog.cob], [0], [], [])

engboris marked this conversation as resolved.
Show resolved Hide resolved
AT_CLEANUP
16 changes: 15 additions & 1 deletion tests/testsuite.src/used_binaries.at
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ AT_CLEANUP


AT_SETUP([check include header file])
#AT_KEYWORDS([cobc copy])
#AT_KEYWORDS([cobc copy include imp])

AT_DATA([filec.h], [
/* COB_EXT_IMPORT will be defined by libcob.h up-front */
Expand Down Expand Up @@ -1171,4 +1171,18 @@ AT_CHECK([$COMPILE_MODULE -Wno-unfinished --copy "f.copy" -fstatic-call prog2.co
AT_CHECK([$COMPILE_MODULE -Wno-unfinished --copy "f.copy" -fstatic-call -L. -lfilec prog2.cob -o prog2c], [0], ignore, ignore)]
)

AT_DATA([prog3.cob], [
>> IMP INCLUDE "file.h"
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.
])

# static build with correct function signature
# AT_CHECK([$COBC -m -I . -fstatic-call prog3.cob], [0], [], [])

AT_CLEANUP
Loading