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

fix m_vsnprintf return value #1077

Merged
merged 12 commits into from
Apr 20, 2017
Merged

fix m_vsnprintf return value #1077

merged 12 commits into from
Apr 20, 2017

Conversation

tius2000
Copy link
Contributor

@tius2000 tius2000 commented Apr 11, 2017

Changed the logic of m_vsnprintf() to return the correct value if the buffer is not large enough (see #1066 ). The overflow guard is no longer required. Unfortunately this required some changes to the existing logic, I hope I did not break anything. Here is a minimal test application:

/*
	test return value of snprintf
	
	expected result:
	
		>123<      5
		>1234<     6
		>12345<    7
		>123456    8
		>123456    9
		% A 777 0x033A > 42< -1 > 3.14< >  123< >123  <
*/	

#include <SmingCore.h>

static void _test(const char *s) {
	char buf[8];
	size_t r = m_snprintf( buf, sizeof(buf), ">%s<", s );
	debugf("%-10.10s %d", buf, r);
}




void init() {
	Serial.begin(74880); 
	debugf("\n\ntest m_snprintf\n");
	
	//	test return values
	_test("123");
	_test("1234");
	_test("12345");
	_test("123456");
	_test("1234567");

	//	minimal format testing
	m_printf(
		"%% %c %o 0x%04X >%3u< %d >%5.2f< >%5.5s< >%-5.5s<\n", 
		65, 0777, 0x33A, 42, -1, 3.14159, "123", "123"
	);
}

Copy link
Contributor

@ADiea ADiea left a comment

Choose a reason for hiding this comment

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

Adding a lambda to take care of size every byte is a great idea. But i don' t like use of gotos especially copy label that jumps cases it's hard to follow imho. No chance of loops instead of gotos?

@tius2000
Copy link
Contributor Author

tius2000 commented Apr 12, 2017

Well, C is not my primary language, but I will try to reduce the number of gotos ;-)

s = dtostrf_p(va_arg(args, double), width, precision, tempNum, pad);
break;

case 'o':
Copy link
Contributor

Choose a reason for hiding this comment

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

I would rewrite as

case 'o':
case 'x':
case 'X':
if('o' == f)
base=8;
else
base=16;
case 'u':

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 are very strict regarding gotos ;-)

I changed it a bit to get rid of the fall-through, too.

@ADiea
Copy link
Contributor

ADiea commented Apr 13, 2017

Have no other remarks. If "unit tests" in basic_string example work ok it's fine with me. Thanks again!

@tius2000 tius2000 mentioned this pull request Apr 18, 2017
@slaff slaff added this to the 3.2.0 milestone Apr 18, 2017
static void defaultPrintChar(uart_t *uart, char c) {
return uart_tx_one_char(c);
return uart_tx_one_char(c);
Copy link
Contributor

Choose a reason for hiding this comment

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

The are multiple white-space changes that are not related to this PR. Please, revert them.

Copy link
Contributor Author

@tius2000 tius2000 Apr 18, 2017

Choose a reason for hiding this comment

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

Sorry, if this is a FAQ - is there a guide regarding source code formatting for Sming (or even better, a command line tool for windows to do the correct formatting)?

I tried to follow the rule 38 here: Special characters like TAB and page break must be avoided.
These characters are bound to cause problem for editors, printers, terminal emulators or debuggers when used in a multi-programmer, multi-platform environment.

That's why I converted all tabs to space before committing.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's why I converted all tabs to space before committing.

Changing of formatting and coding style can happen in another PR. This PR is only related to m_vsnprintf changes.

@slaff slaff self-assigned this Apr 18, 2017
@tius2000
Copy link
Contributor Author

  • support for format and data strings in PROGMEM added
  • format specifier '%S' added for compatibility (behaves like '%s)
  • m_vprintf now allocates less memory on the stack unless it is actually required

There is no longer a need for separate *_P methods, this should make it easier to solve the conflicts created by the macro printf_P in FakePgmSpace.h.

Copy link
Contributor

@slaff slaff left a comment

Choose a reason for hiding this comment

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

Please, move the PROGMEM changes to another PR. This one should be only related to return value of m_vsnprinf. If we have two PRs it will be easier to test and easier to find the cause of the issues, if any.

// need to retry if size is not big enough
while (1) {
char buffer[size + 1];
auto sz = m_vsnprintf(buffer, sizeof(buffer), fmt, va);
Copy link
Contributor

Choose a reason for hiding this comment

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

Please, change auto to size_t.

n++;
p++;
const char *p = buffer;
while (char c = *p++) cbc_printchar(cbc_printchar_uart, c);
Copy link
Contributor

Choose a reason for hiding this comment

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

Format the while with opening and closing curly braces.

while (char c = *p++)  {
     cbc_printchar(cbc_printchar_uart, c);
}

if (++size < maxLen) *buf++ = c;
};

while ( char f = pgm_read_byte(fmt) ) {
Copy link
Contributor

Choose a reason for hiding this comment

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

If you read every byte using pgm_read_byte that will cause overhead. Is that really needed in a very core component? What are the advantages?

Copy link
Contributor Author

@tius2000 tius2000 Apr 19, 2017

Choose a reason for hiding this comment

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

You a right, this will make every call to *printf a tiny bit slower. The code size is almost identical. I see the following advantages:

  • it will reduce total flash size and complexity as a many additional methods are no longer needed
  • all classes and methods using m_printf will benefit immediately
  • life will be much easier for users as they do not need to care which method to call and which format specifier to use
  • format strings should go to flashmem anyway to reduce ram size
  • it is faster and uses less memory than the existing implementation for format strings in flashmem
  • printf is mostly used for serial output where execution speed does not matter that much
  • for time critical operations direct c string manipulation should be used instead of the printf functions

IMHO the main advantage is that it eliminated a major pitfall for users working with progmem.

@tius2000
Copy link
Contributor Author

I'm quite new to GitHub - how can I create a PR that depends on another PR?

@slaff
Copy link
Contributor

slaff commented Apr 19, 2017

I'm quite new to GitHub - how can I create a PR that depends on another PR?

Create a branch for PR 1. Work on it until you are ready. Then create another branch for PR1 that is based on PR1.

git check PR1
# ... work...
# .... ready
git branch PR2
git checkout PR2
# additional work 

If there are changes in PR1 you can keep PR2 up to date using the following commands:

git checkout PR1 
# .. make sure that you have the latest code for PR1
git checkout PR2
git merge PR1
# git mergetool # if needed
git rebase PR1
# git mergetool # if needed
git push -f 

That should be it.

@tius2000
Copy link
Contributor Author

tius2000 commented Apr 19, 2017

I created a new PR #1096 that way, hope I got it right! Also moved the stacksize change to new PR (#1097).

@slaff slaff removed the 3 - Review label Apr 20, 2017
@slaff slaff merged commit abcf6a2 into SmingHub:develop Apr 20, 2017
@tius2000 tius2000 deleted the m_printf_1704 branch April 20, 2017 07:50
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