Skip to content

Initial @file#289

Open
RamyGeorge wants to merge 7 commits into
OCamlPro:gitside-gnucobol-3.xfrom
RamyGeorge:initial-atfile
Open

Initial @file#289
RamyGeorge wants to merge 7 commits into
OCamlPro:gitside-gnucobol-3.xfrom
RamyGeorge:initial-atfile

Conversation

@RamyGeorge

Copy link
Copy Markdown

Summary

This pull request is intended to introduce the "@file" command line option to GnuCOBOL.

Motivation

Such option would no longer limit the amount of options to that of a given OS's Terminal size.

Changes

  • added initial implementation for "@" detection and reading File contents
  • Called new process_at_file in process_command_line

Misc

I Have left a few notes on current changes and hope for feedback

Comment thread cobc/cobc.c Outdated
if (atfile_options) break;
}
if (cobc_compile_mode) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I initially thought i could "naively" realloc argv with new input but a simple Stack Overflow entry proved this can't be done

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we'll need a force-push from a new local branch to not includes screen changes, it may or may not cherry-pick the current commit on that)

We then need test cases which also shows what the implementation wants to provide and then can have a look if the proposed changes work that way (= work on getting it there).

Comment thread libcob/cobgetopt.c Outdated
Comment on lines +496 to +500
if (!path) {
free(path_str);
fprintf(stderr,"File is non existent or invalid path");
return "";
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

as seen in the GCC "spec" (documentation for @file) -> there is no warning/error to raise, the "option" is just passed as a "normal" file, so cobc will then do its normal error handling later

Comment thread libcob/cobgetopt.c Outdated
Comment on lines 601 to 606
#define NONOPTION_P ((argv[optind][0] != '-' && argv[optind][0] != '@') || argv[optind][1] == '\0')

if (argv[optind][0] == '@'){
return '@'; /*Most definitly is wrong but im messing around*/
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

as discussed - we need to do it all up-front and build a completely new argv/argc before even going to the getopt call

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

As seen in CI that currently leads to a SEGFAULT:

1197. run_extensions.at:1761: testing CALL unusual PROGRAM-ID. ...
../../tests/run_extensions.at:1815: $COMPILE_MODULE A@B.cob
/tmp/_actions-runner-working-dir/gnucobol/gnucobol/_build/tests/testsuite.dir/at-groups/1197/test-source: line 154: 75721 Segmentation fault      (core dumped) ( $at_check_trace; $COMPILE_MODULE A@B.cob ) >> "$at_stdout" 2>> "$at_stderr" 5>&-
--- /dev/null	2026-04-27 01:59:42.626967408 +0000
+++ /tmp/_actions-runner-working-dir/gnucobol/gnucobol/_build/tests/testsuite.dir/at-groups/1197/stderr	2026-05-18 21:19:44.588745273 +0000
@@ -0,0 +1,5 @@
+
+attempt to reference invalid memory address (signal SIGSEGV)
+
+cobc: aborting
+cobc: Please report this!
../../tests/run_extensions.at:1815: exit code was 139, expected 0
1197. run_extensions.at:1761:  FAILED (run_extensions.at:1815)

so there is still some stuff to do :-)

Most important: please always add Changelog entries as those document the changes you did - also helps for review - and getting the habit of always documenting at least on git push is a good thing; similar applies for the testsuite (would go into used_binaries.at)

Comment thread cobc/cobc.c
Comment thread cobc/cobc.h Outdated
extern int cobc_wants_debug;
extern int cb_listing_xref;
extern int cobc_seen_stdin;
extern int cobc_compile_mode; /*0 for in-terminal command options, 1 for @file */

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

unused so can be dropped

Comment thread libcob/cobgetopt.h Outdated

char * process_at_file(const char* argument_values,int* compile_mode,int* atfile_size);
char** expand_processed_at_file(char *options, int *output_argc);
void rebuild_argv_at_file(int * old_argc, char*** old_argv);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

we only need to externalize one -> that should have a "cob_" prefix, the others can be static in cobgetopt.c

Comment thread libcob/cobgetopt.c Outdated
free(path_str);


int ret;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

as discussed, that won't build when using configure CC="gcc -std=c89" CPPFLAGS="-Werror=declaration-after-statement" (or an old compiler, which is the reason why we check that)

Comment thread libcob/cobgetopt.c Outdated
}
size_t path_size = endptr - ptr + 1;
/* Ptr->endptr carries the directory */
char* path_str = malloc(path_size);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

instead of a short-lived malloc on the heap use one of the following two approaches:

1 clean, wasteful: local buffer with local #definedd max
2 hacker-way: const char orig = *endptr; *endptr = 0; /*later* *endptr=orig;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

still open - you don't need the malloc here and then also don't need to free the string anywhere later

Comment thread libcob/cobgetopt.c Outdated
process_at_file(const char* argument_values,int* compile_mode,int* atfile_size){
char * ptr = strstr(argument_values,"@");
if (ptr){
*compile_mode = 1;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

this parameter var seems obsolete altogether

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This parameter still seems obsolete to me, why not dropping it?

Also: just checking for !ptr and return here can make the code easier to follow

Comment thread libcob/cobgetopt.c Outdated
Comment on lines +504 to +510
if(length+1 >= capacity){
capacity *= 4;
char *newoptions = realloc(options, capacity);
options = newoptions;
}

options[length++] = (char)ret;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is there a reason to not tokenize here?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

toekenize = embedding code of expand_processed_at_file here (but directly wit the token), maybe even recursively call FUNC if the arg seen starts with an @?

Comment thread libcob/cobgetopt.c Outdated

@GitMensch GitMensch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

nice progress

Comment thread libcob/cobgetopt.c Outdated
}
size_t path_size = endptr - ptr + 1;
/* Ptr->endptr carries the directory */
char* path_str = malloc(path_size);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

still open - you don't need the malloc here and then also don't need to free the string anywhere later

Comment thread libcob/cobgetopt.c Outdated
FILE* path = fopen(path_str, "r");
size_t capacity = 256;
size_t length = 0;
char *options = malloc(capacity);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

declare options here, but malloc after the path check

Comment thread cobc/cobc.c
Comment thread cobc/cobc.c
Comment thread libcob/cobgetopt.c Outdated
process_at_file(const char* argument_values,int* compile_mode,int* atfile_size){
char * ptr = strstr(argument_values,"@");
if (ptr){
*compile_mode = 1;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This parameter still seems obsolete to me, why not dropping it?

Also: just checking for !ptr and return here can make the code easier to follow

Comment thread libcob/cobgetopt.c Outdated
Comment on lines +504 to +510
if(length+1 >= capacity){
capacity *= 4;
char *newoptions = realloc(options, capacity);
options = newoptions;
}

options[length++] = (char)ret;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

toekenize = embedding code of expand_processed_at_file here (but directly wit the token), maybe even recursively call FUNC if the arg seen starts with an @?

Comment thread libcob/cobgetopt.c Outdated
/* Test whether ARGV[optind] points to a non-option argument. */
#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0')


Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

revert this non-change for cleaner diff

$COMPILE_MODULE @tempfile.txt prog.cob], [1], [],
[cobc: error: only one of options 'm', 'x', 'b' may be specified
])
AT_CLEANUP()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

end with an empty line, but add more tests here: @something (= not an existing file) should be passed as is

if not yet implemented move to another test: multiple @file (including the error case A -> B -> C -> A)

Comment thread tests/testsuite.src/used_binaries.at Outdated
STOP RUN.
])

AT_CHECK([echo "-x" > tempfile.txt

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

just use AT_DATA for that

Comment thread tests/testsuite.src/used_binaries.at Outdated


AT_SETUP(@file command line options)
AT_KEYWORDS([syntax])

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

that looks like the wrong keyword, "cobc" is likely useful here, as well as "getopt", that will then also allow you to VGSUFFIX=mytests make check TESTSUITEFLAGS="-k getopt" to verify your changes via valgrind (also see https://sourceforge.net/p/gnucobol/wiki/Hacking%20GnuCOBOL/)

Comment thread libcob/cobgetopt.c Outdated
Comment on lines 493 to 499
@@ -500,11 +498,11 @@ process_at_file(const char* argument_values,int* compile_mode,int* atfile_size){
return NULL;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

the old code here was better, you just need to add an additional scope {} around that; note that I'd suggest to do the define here and use all upper-case with a name that is unlikely conflict with any system header

Comment thread libcob/cobgetopt.c Outdated
@RamyGeorge RamyGeorge force-pushed the initial-atfile branch 2 times, most recently from dd0e41a to 9dbd453 Compare June 2, 2026 16:03
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 65.51724% with 30 lines in your changes missing coverage. Please review.
⚠️ Please upload report for BASE (gitside-gnucobol-3.x@a3accbe). Learn more about missing BASE report.

Files with missing lines Patch % Lines
libcob/cobgetopt.c 64.70% 22 Missing and 8 partials ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Additional details and impacted files
@@                   Coverage Diff                   @@
##             gitside-gnucobol-3.x     #289   +/-   ##
=======================================================
  Coverage                        ?   67.44%           
=======================================================
  Files                           ?       34           
  Lines                           ?    61615           
  Branches                        ?    16051           
=======================================================
  Hits                            ?    41555           
  Misses                          ?    14107           
  Partials                        ?     5953           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants