# Introduction
When compiling a source file you see an error diagnostic similar to ...
```
"file.c", line 5: error: too few arguments in function call
```
When you look at the problem source line, you see it is a call to the function
ltoa. How should this error be handled?
# Overview
Some background on the ltoa function is given. The change is explained.
Alternatives to ltoa are reviewed. Three methods are shown for how you can
change your code to fix the error.
# Background
The function ltoa takes a long integer value and converts it into an ASCII
string. It is **not** among the runtime support functions required by the
ANSI standard for C. Even so, TI has supplied an ltoa function for many
years. It started as a helper to the printf family of functions. It was
never documented.
The interface to ltoa changed. In older versions of TI compilers, this is
the interface ...
```
int ltoa(long val, char *buffer); /* OLD */
```
In newer versions of TI compilers, the interface is different ...
```
char *ltoa(long val, char *buffer, int radix); /* NEW */
```
The older ltoa returns an int, and takes 2 arguments. The newer ltoa returns
a pointer to char, and takes 3 arguments. The newer ltoa matches the
implementation that comes with many other commonly used C compilers.
# Version Information
The change to ltoa is introduced in these versions of the compiler.
Target | Version
-------|--------
ARM | 19.6.0.STS
MSP430 | 19.6.0.STS
C28x | 19.6.0.STS
ARP32 | 1.1.0
PRU | 2.3.2
C6000 | 8.2.6
C6000 | 8.3.3
For C6000, in the series of version 8.2.x releases, the change is introduced
in version 8.2.6. For C6000, in the series of version 8.3.x releases, the
change is introduced in version 8.3.3.
As of this writing, ARP32 compiler version 1.1.0 is not available.
# Alternatives to ltoa
It may make sense to replace a call to ltoa with one of these alternatives.
- sprintf
- A custom implementation with a different name
# Changing Your Code
How might you change your code that calls ltoa to account for this change?
Three methods are shown, each more elaborate than the previous. Use the one
that best fits your needs.
## Method One
### Presumptions
- Return value is not used
- Portability is **not** a concern
- Between different compilers
- Between different versions of the same compiler
### Details
In this case, add the value 10 as the third argument.
```
ltoa(value, local_buffer); /* OLD */
ltoa(value, local_buffer, 10); /* NEW */
```
The third argument to the new ltoa is the radix used when converting to the
string. The implied radix of the old ltoa is 10, for decimal numbers.
## Method Two
### Presumptions
- Only one compiler is used
- The compiler is a TI compiler
- Must be portable between different versions of that compiler
### Details
The goal of this method is to create the preprocessor symbol OLD_LTOA, or the
preprocessor symbol NEW_LTOA.
All TI compilers support a predefined preprocessor symbol named
\_\_TI\_COMPILER\_VERSION\_\_. It contains, in decimal number form, an
encoding of the version of the compiler. This table shows, for each target
CPU, the value of \_\_TI\_COMPILER\_VERSION\_\_ which introduces the change to
ltoa.
Target | TCV Value
-------|----------
ARM | 19006000
MSP430 | 19006000
C28x | 19006000
ARP32 | 1001000
PRU | 2003002
C6000 | Details below
TCV, in the second column title, stands for TI Compiler Version.
The following example is for the TI ARM compiler. To adapt it to another
compiler, replace 19006000 with the TCV Value from the table above.
In a header file which is included by all source files that call ltoa, have
lines similar to the following:
```
#if __TI_COMPILER_VERSION__ < 19006000
#define OLD_LTOA
#else
#define NEW_LTOA
#endif
```
A call to ltoa could be changed to something similar to ...
```
#ifdef OLD_LTOA
ltoa(value, local_buffer);
#else
ltoa(value, local_buffer, 10);
#endif
```
To understand the details of how the \_\_TI\_COMPILER\_VERSION\_\_ numbers
work, please search the relevant target
[compiler manual](https://www.ti.com/tool/TI-CGT#technicaldocuments)
for the sub-chapter titled *Predefined Macro Names*.
### Details for C6000
Since the change is introduced on two different streams of related versions
of the compiler, the version comparison is a bit more complicated.
```
/* Create a shorter name, so the comparison is easier to read */
#define TCV __TI_COMPILER_VERSION__
#if TCV < 8002006 || (8003000 <= TCV && TCV <= 8003002)
#define OLD_LTOA
#else
#define NEW_LTOA
#endif
/* No longer need the shorter name */
#undef TCV
```
## Method Three
### Presumptions
- Any compiler may be used
- TI and non-TI compilers
- Any version
### Details
The goal of this method is, for non-TI compilers, to do nothing. If it is a
TI compiler, then create the preprocessor symbol OLD_LTOA, or the preprocessor
symbol NEW_LTOA.
In a header file which is included by all source files that call ltoa, have
lines similar to the following:
```
/* Do nothing for a non-TI compiler */
#if defined(__TI_COMPILER_VERSION__)
/* Create a shorter name, to make the comparison easier to read */
#define TCV __TI_COMPILER_VERSION__
#if (defined(__TI_ARM__) && TCV < 19006000) \
|| (defined(__MSP430__) && TCV < 19006000) \
|| (defined(__TMS320C2000__) && TCV < 19006000) \
|| (defined(__ARP32__) && TCV < 1001000) \
|| (defined(__PRU__) && TCV < 2003002) \
|| (defined(__TMS320C6X__) && \
(TCV < 8002006 || (8003000 <= TCV && TCV <= 8003002)))
#define OLD_LTOA
#else
#define NEW_LTOA
#endif
/* No longer need the shorter name */
#undef TCV
#endif /* defined(__TI_COMPILER_VERSION__) */
```
The preprocessor symbols \_\_TI\_ARM\_\_, \_\_MSP430\_\_, etc. are predefined
by those particular TI compilers.