Skip to content

Commit

Permalink
Add >>IMP INCLUDE directive
Browse files Browse the repository at this point in the history
  • Loading branch information
engboris committed Jun 13, 2024
1 parent 21b5d51 commit a2d9a5e
Show file tree
Hide file tree
Showing 10 changed files with 216 additions and 6 deletions.
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)

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;
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;
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]+

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;
}
}
;

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 {
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);
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])
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], [],
[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.
])

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

AT_CLEANUP
47 changes: 46 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,49 @@ 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

AT_SETUP([check include header file with directive])
#AT_KEYWORDS([imp include])

AT_DATA([file.h], [
COB_EXT_IMPORT void f (char *, long);
])
AT_DATA([prog.cob], [
>> IMP INCLUDE "file.h"
IDENTIFICATION DIVISION.
PROGRAM-ID. prog.
PROCEDURE DIVISION.
CALL "f" USING "Hello".
])

AT_CHECK([$COBC -m -I . -fstatic-call prog.cob], [1], [], [ignore])

AT_DATA([prog2.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.
])

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

AT_CLEANUP

0 comments on commit a2d9a5e

Please sign in to comment.