Structorizer.Desktop icon indicating copy to clipboard operation
Structorizer.Desktop copied to clipboard

On C import, neither direct struct, enum etc. definitions nor (structured) typedefs from header files are imported as type declarations

Open codemanyak opened this issue 1 year ago • 4 comments

Though structured typedefs found in headers for used type names make a C source file pass the C99 parser (with bugfix #1085 integrated), they don't induce a type declaration in an includable diagram on C import. (This happens only if the typedef or struct definition occurs in the C file itself).

Example:

File version 1 (C flile with integrated type definition):

typedef struct Date {
	int year;
	unsigned short month;
	unsigned short day;
} Date_t;

bool isValid(const Date_t aDate)
{
	unsigned short days = getMonthLength(aDate.month, aDate.year);
	return (days > 0 && aDate.day <= days);
}

unsigned short getMonthLength(unsigned short month, int year)
{
	unsigned short days = 0;
	switch (month) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			days = 31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			days = 30;
			break;
		case 2:
			days = 28;
			if (isLeapYear(year)) {
				days++;
			}
			break;
	}
	return days;
}

bool isLeapYear(int year)
{
	return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}

results in: grafik

File version 2 (properly decomposed in header and C file):

Date.h

#ifndef DATE_H
#define DATE_H

#include <stdbool.h>

typedef struct Date {
	int year;
	unsigned short month;
	unsigned short day;
} Date_t;

bool isValid(const Date_t aDate);

unsigned short getMonthLength(unsigned short month, int year);

bool isLeapYear(int year);

#endif DATE_H

Date.c

#include "Date.h"

bool isValid(const Date_t aDate)
{
	unsigned short days = getMonthLength(aDate.month, aDate.year);
	return (days > 0 && aDate.day <= days);
}

unsigned short getMonthLength(unsigned short month, int year)
{
	unsigned short days = 0;
	switch (month) {
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
			days = 31;
			break;
		case 4:
		case 6:
		case 9:
		case 11:
			days = 30;
			break;
		case 2:
			days = 28;
			if (isLeapYear(year)) {
				days++;
			}
			break;
	}
	return days;
}

bool isLeapYear(int year)
{
	return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
}

results in (and causes Analyser warnings, particularly on component access): grafik

codemanyak avatar Sep 12 '23 22:09 codemanyak

It seems to be a sensible way to have the file preparation phase (which scans the included header files) copy the structure definitions into the C file selected for import (as the C preprocessor does for the the C parser). An even more sensible approach might be directly to derive an includable diagram from every header file, i.e. to reflect the header structure by an analogous system of Includables. This operation ought to be made optional, i.e., a language-specific preference.

codemanyak avatar Sep 12 '23 23:09 codemanyak

On the other hand, if a declaration (e.g. variable or argument) refers to a struct name in the traditional C manner without typedef, i.e., by using the struct prefix, then Structorizer fails to eliminate the struct keyword in the diagram: grafik

codemanyak avatar Sep 12 '23 23:09 codemanyak

I wrote in https://github.com/fesch/Structorizer.Desktop/issues/1087#issuecomment-1716632402:

It seems to be a sensible way ...

It will be an important decision whether to transform all representable defined stuff from the header files or to filter them by actual usage in the C file. This is not only a question of efforts. The filtering would be more feasible (and sensible) in the approach to copy needed definitions into the source file, whereas for the direct header-to-includable approach it would be more natural not to filter. By the way, even the copy approach is likely to produce Includables - as soon as more than one function of the C file refers to a defined type. But in this case at most one, common Includable would be created.

codemanyak avatar Sep 13 '23 07:09 codemanyak

Well, the implementation turns out to be more complex than initially assumed, at least if the existing code is not to be rewritten completely. So it will reqire a deeper insight. We will also have to care e.g. for constants, for all kind of struct, enum, and union definition, not just typedefs alone as before.

codemanyak avatar Sep 15 '23 16:09 codemanyak