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 Apr 30, 2024
1 parent 87c4fb2 commit 7bb6097
Show file tree
Hide file tree
Showing 11 changed files with 263 additions and 3 deletions.
2 changes: 2 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ 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" 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
6 changes: 6 additions & 0 deletions cobc/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
replace stream) and we use a circular buffer for the temporary
queue of tokens instead of a list.

2024-04-25 Boris Eng <[email protected]>

* 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-03-17 Fabrice Le Fessant <[email protected]>
Emilien Lemaire <[email protected]>

Expand Down
1 change: 1 addition & 0 deletions cobc/cobc.c
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ 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_file_list_directive = 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
2 changes: 2 additions & 0 deletions cobc/cobc.h
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ 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_file_list_directive;
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 Expand Up @@ -597,6 +598,7 @@ extern unsigned int ppparse_verify (const enum cb_support tag,
extern void ppparse_error (const char *);

extern int cobc_deciph_source_format (const char *);
extern int cobc_deciph_header_filename (const char *);
extern void cobc_set_source_format (const enum cb_format);
extern enum cb_format cobc_get_source_format (void) COB_A_PURE;
extern int cobc_get_indicator_column (void) COB_A_PURE;
Expand Down
20 changes: 17 additions & 3 deletions cobc/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -1830,14 +1830,28 @@ 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 = cb_include_file_list;
struct cb_text_list *ld = cb_include_file_list_directive;
struct cb_text_list *next;
for (;l;l=l->next) {
if (l->text[0] == '<') {
output_line ("#include %s", l->text);
} else {
output_line ("#include \"%s\"", l->text);
}
}
while (ld) {
if (ld->text[0] == '<') {
output_line ("#include %s", ld->text);
} else {
output_line ("#include \"%s\"", ld->text);
}
next = ld->next;
if (next != NULL)
free (ld);
ld = next;
}
cb_include_file_list_directive = NULL;
}

}
Expand Down
28 changes: 28 additions & 0 deletions cobc/pplex.l
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,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 +361,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 +730,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 +1000,14 @@ ENDIF_DIRECTIVE_STATE>{
}
}

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

<IF_DIRECTIVE_STATE>{
"IS" { return IS; }
"NOT" { return NOT; }
Expand Down Expand Up @@ -1867,6 +1882,19 @@ int cobc_deciph_source_format (const char *sfname) {
return 1;
}

int cobc_deciph_header_filename (const char *filename) {
size_t n = strlen(filename);
if (filename[0] == '<' && filename[n-1] == '>' &&
filename[n-3] == '.' && filename[n-2] == 'h') {
return 0;
} else if (filename[n-2] == '.' && filename[n-1] == 'h') {
return 0;
}
else {
return 1;
}
}

void
plex_clear_vars (void)
{
Expand Down
34 changes: 34 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,35 @@ 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
{
char *f = fix_filename ($1);
if (cobc_deciph_header_filename (f) != 0)
ppp_error_invalid_option ("IMP", f);
$$ = ppp_list_add (NULL, f);
}
| imp_include_sources TOKEN
{
char *f = fix_filename ($2);
if (cobc_deciph_header_filename (f) != 0)
ppp_error_invalid_option ("IMP", f);
$$ = ppp_list_add ($1, f);
}
;

turn_directive:
ec_list CHECKING on_or_off
{
Expand Down
38 changes: 38 additions & 0 deletions cobc/scanner.l
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,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 +324,14 @@ AREA_A "#AREA_A"\n
cobc_areacheck = 0;
}

<*>^[ ]?"#INCLUDE".*\n {
yytext[strlen(yytext)-1] = '\0';
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 @@ -1297,6 +1306,17 @@ H#[0-9A-Za-z]+ {
}
}

<PICTURE_STATE>{
"IS" {
/* Ignore */
}
[^ \n;]+ {
BEGIN INITIAL;
scan_picture (yytext);
RETURN_TOK (PICTURE);
}
}

<<EOF>> {
/* At EOF - Clear variables */
clear_constants ();
Expand Down Expand Up @@ -2583,6 +2603,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_plex_malloc (sizeof (struct cb_text_list));
p->text = cobc_plex_strdup (text);
if (!list) {
p->last = p;
return p;
}
list->last->next = p;
list->last = p;
return list;
}

/* Global functions */

void
Expand Down Expand Up @@ -2772,3 +2808,5 @@ cb_find_defined_program_by_id (const char *orig_id)

return NULL;
}


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
102 changes: 102 additions & 0 deletions tests/testsuite.src/syn_misc.at
Original file line number Diff line number Diff line change
Expand Up @@ -8385,3 +8385,105 @@ 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_CLEANUP

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

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

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

AT_CLEANUP

AT_SETUP([IMP INCLUDE directive file format])
AT_KEYWORDS([IMP INCLUDE])

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

AT_CHECK([$COMPILE_ONLY -fformat=free prog.cob], [1], [],
[prog.cob:2: error: invalid IMP directive option 'file'
])

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

AT_CHECK([$COMPILE_ONLY -fformat=free prog.cob], [1], [],
[prog.cob:2: error: syntax error, unexpected ., expecting Word or Literal
prog.cob:2: error: PROGRAM-ID header missing
prog.cob:2: error: syntax error, unexpected end of file, expecting SECTION
])

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

AT_CHECK([$COMPILE_ONLY --fformat=free prog.cob], [1], [],
[prog.cob:2: error: invalid IMP directive option 'file2'
])

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

AT_CHECK([$COMPILE_ONLY --fformat=free prog.cob], [1], [],
[prog.cob:2: error: PROGRAM-ID header missing
prog.cob:2: error: ENVIRONMENT DIVISION header missing
prog.cob:2: error: CONFIGURATION SECTION header missing
prog.cob:2: error: SPECIAL-NAMES header missing
prog.cob:2: error: invalid system-name 'file2'
prog.cob:2: error: invalid symbol '#' - skipping word
prog.cob:2: error: invalid system-name 'h'
prog.cob:4: error: syntax error, unexpected IDENTIFICATION, expecting CRT or Identifier
prog.cob:4: error: syntax error, unexpected DIVISION
])

AT_CLEANUP
Loading

0 comments on commit 7bb6097

Please sign in to comment.