Subversion Repositories wimsdev

Rev

Rev 13927 | Rev 14856 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 13927 Rev 13932
Line 1... Line 1...
1
/*
1
/*
2
*********************************************************************************
2
*********************************************************************************
3
* J.M. Evers 2/2012                                                             *
3
* J.M. Evers 3/2012                                                             *
4
* This is all amateur scriblings... So no copyrights.                           *
4
* This is all amateur scriblings... So no copyrights.                           *
5
* This source code file, and compiled objects derived from it,                  *
5
* This source code file, and compiled objects derived from it,                  *
6
* can be used and distributed without restriction, including for commercial use *
6
* can be used and distributed without restriction, including for commercial use *
7
* No warrenty whatsoever                                                        *
7
* No warrenty whatsoever                                                        *
8
*********************************************************************************
8
*********************************************************************************
-
 
9
general use:
-
 
10
rounding to 2 decimals (financial math)
-
 
11
tot=!exec moneyprint 0.1,17,123.4,123.99765
-
 
12
tot -> 0.10,17.00,123.40,124.00
9
 
13
 
10
general use:
-
 
11
moneyprint number1,number2,number3... DECIMALS
-
 
12
default rounding to 2 decimals (financial math)
-
 
13
 
-
 
14
tot=!exec moneyprint 6.14512 --> 6.15
-
 
15
tot=!exec moneyprint 6.14512 3 --> 6.145
-
 
16
tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0.10,17.00,123.40,124.00
-
 
17
tot=!exec moneyprint 2*10^7,2E-7 --> 2.00*10^7,2.00*10^-7
-
 
18
!set use_comma
-
 
19
# only for representation ,the outcome can not be used for further arithmetics/calculations
-
 
20
tot=!exec moneyprint 6.14512 --> 6,15
-
 
21
tot=!exec moneyprint 6.14512 3 --> 6,145
-
 
22
tot=!exec moneyprint 0.1,17,123.4,123.99765 --> 0,10 17,00 123,40 124,00
-
 
23
tot=!exec moneyprint 2*10^7,2E-7 --> 2,00*10^7 2,00*10^-7
-
 
24
 
-
 
25
bugs & flaws: no calculations are performed , fractions are not supported
-
 
26
 
-
 
27
CHANGELOG
-
 
28
2/2012
14
2/2012
29
 modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers
15
 modified for general rounding usage; a word 'DECIMALS' can be added to the list of numbers
30
 tot=!exec moneyprint 2.1,4.123,5  2   // 2 decimals
16
 tot=!exec moneyprint 2.1,4.123,5  2   // 2 decimals
31
 tot -> 2.10,4.12,5.00
17
 tot -> 2.10,4.12,5.00
32
 tot=!exec moneyprint 2.1,4.123,5  4   // 4 decimals
18
 tot=!exec moneyprint 2.1,4.123,5  4   // 4 decimals
33
 tot -> 2.1000,4.1230,5.0000
19
 tot -> 2.1000,4.1230,5.0000
34
 tot=!exec moneyprint 2.1,4.123,5
20
 tot=!exec moneyprint 2.1,4.123,5
35
 tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals  
21
 tot -> 2.10,4.12,5.00 //default value (or old syntax) is 2 decimals  
36
 
22
 
37
6/2012
23
6/2012.
38
 modified again to support rounding of scientific numbers, like
24
 modified again to support rounding of scientific numbers, like
39
 tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3
25
 tot=!exec moneyprint 1.23456e+06,1.23456*10^6,0.01234e-23 3
40
 tot -> 1.235e06,1.235e6,0.012e-23
26
 tot -> 1.235e06,1.235e6,0.012e-23
-
 
27
 
41
 assumed only powers of 10 [scientific notation]
28
 assumed only powers of 10 [scientific notation]
42
 
29
 
43
12/2012
30
12/2012
44
 Modified : using only 10^ in powers
31
Modified : using only 10^ in powers
45
 (e+8 -> *10^8 ; e-8 -> *10^-8)
32
(e+8 -> *10^8 ; e-8 -> *10^-8)
46
 Extra syntax error signal (using more than 1 'e')
33
Extra syntax error signal (using more than 1 'e')
47
 
34
 
48
27/2014
35
27/2014
49
 Modified avoiding truncating of numbers like 15.625 --> 16.62
36
Modified avoiding truncating of numbers like 15.625 --> 16.62
50
 
37
 
51
2/2018
-
 
52
 if variable "w_use_comma" is set (eg in phtml !set use_comma=1), the result is a comma 'decimal' separator:
-
 
53
 moneyprint 1.2345 2 -> 1,23
-
 
54
 moneyprint 1.2345 , 2.34567 , 3.4567 , 5 2 -> 1,23 2,35 3,46 5,00
-
 
55
 (note: in this case (multiple conversions) we use 'spaces' instead of an item ',' list )
-
 
56
 This is INCOMPATIBLE with calculating software : only suitable for REPRESENTATION of (money) numbers
-
 
57
 If env. variable w_use_comma is not set or not "1" , the behaviour is a number with a decimal point
-
 
58
 
-
 
59
5/2019 use "strlcpy, strlcat" - size-bounded string copying and concatenation
-
 
60
*/
38
*/
61
 
39
 
62
#include <stdio.h>
40
#include <stdio.h>
63
#include <stdlib.h>
41
#include <stdlib.h>
64
#include <string.h>
42
#include <string.h>
65
#include <math.h>
43
#include <math.h>
66
#include <locale.h>
-
 
67
 
-
 
68
#define MAX_DIGITS 128
44
#define MAX_DIGITS 32
69
#define MAX_CONV 32
45
#define MAX_CONV 32
70
#define LOCALE "fr_FR.ISO8859-1"
-
 
71
 
-
 
72
 
46
 
73
int main( int argc , char *argv[]){
47
int main( int argc , char *argv[]){
74
 if( argc != 2 && argc != 3){
48
    if( argc != 2 && argc != 3){
75
  fprintf(stdout,"error !\nusage:\n!exec moneyprint $your_wims_item_list $precision_word\nexample:\nmoney=!exec moneyprint 1.2,30.1,.4,-.23123456 2\nThe result is a comma separated list: 1.20,30.10,0.40,-0.23\n using 2 decimals\nNote: no calculations are done.\nNo spaces allowed \n");
49
        fprintf(stdout,"error !\nusage:\n!exec moneyprint $your_wims_item_list $precision_word\nexample:\nmoney=!exec moneyprint 1.2,30.1,.4,-.23123456 2\nThe result is a comma separated list: 1.20,30.10,0.40,-0.23\n using 2 decimals\nNote: no calculations are done.\nNo spaces allowed \n");
76
  exit(0);
50
        exit(0);
77
 }
51
    }
78
 /* test for illegal characters */
52
    /* test for illegal characters */
79
 const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|";
53
    const char *invalid_characters = "\n\"\'!=ABCDFGHIJKLMNOPQRSTUVWYZabcdfghijklmnopqrstuvwyz@#$%&()[]{};:~><?/\\|";
80
 /* +-*^XxEe are allowed : 12.34e+05  12.34e-08 1x10^5 1.234*10^123*/
54
    /* +-*^XxEe are allowed : 12.34e+05  12.34e-08 1x10^5 1.234*10^123*/
81
 char *input;
55
    char *input;
82
 input = argv[1];
56
    input = argv[1];
83
 while (*input){
57
    while (*input){
84
  if ( strchr(invalid_characters, *input) ){
58
        if ( strchr(invalid_characters, *input) ){
85
   fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input);
59
            fprintf(stdout,"error !\nfound illegal character \"%c\" in argument\n",*input);
86
   exit(0);
60
            exit(0);
87
  }
61
        }
88
  input++;
62
        input++;
89
 }
63
    }
90
 int DECIMALS;
64
    int DECIMALS;
91
 if(argv[2] != NULL){
65
    if(argv[2] != NULL){
92
  DECIMALS = atoi(argv[2]);
66
        DECIMALS = atoi(argv[2]);
93
  if(DECIMALS > MAX_DIGITS){
67
        if(DECIMALS > MAX_DIGITS){
94
   fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0);
68
            fprintf(stdout,"error ! maximum amount of decimals is %d \n",MAX_DIGITS);exit(0);
95
  }
69
        }
96
 }
70
    }
97
 else
71
    else
98
 {
72
    {
99
  DECIMALS = 2;
73
        DECIMALS = 2;
100
 }
74
    }
101
 char *sep = ",";
-
 
102
 char *ptr;
75
    char *ptr;
103
 char word[MAX_DIGITS];
76
    char word[MAX_DIGITS];
104
 char exponent[MAX_DIGITS];
77
    char exponent[MAX_DIGITS];
105
 char number[MAX_DIGITS];
78
    char number[MAX_DIGITS];
-
 
79
    int cnt = 1;
106
 char *w_use_comma = getenv("w_use_comma");
80
    int powE = 0;
-
 
81
    int idx1 = 0;
-
 
82
    int idx2 = 0;
107
 if( w_use_comma == NULL ){ w_use_comma = "0";}
83
    int length= 0;
-
 
84
    int i = 0;
108
 int cnt = 1;int powE = 0;int idx1 = 0;int idx2 = 0;int length = 0;int i = 0;int pow10 = 0;
85
    int pow10 = 0;
109
 double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */
86
    double correction = 1/(pow(10,DECIMALS+6)); /* a reasonable guess...to avoid truncating 15.625 --> 16.63 */
110
 double ascii_number;
87
    double ascii_number;
111
 input = argv[1];
88
    input = argv[1];
112
 ptr = strtok(input,",");
89
    ptr = strtok(input,",");
113
 while( ptr != NULL){
90
    while( ptr != NULL){
-
 
91
        if(  cnt > MAX_CONV ){
114
  if(  cnt > MAX_CONV ){fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV);exit(0);}
92
            fprintf(stdout,"ERROR too many (> %d)conversion \n",MAX_CONV);
-
 
93
            exit(0);
-
 
94
        }
115
  /* next item in input argv[1] */
95
        // next item in input argv[1]
116
  strlcpy( word, ptr, sizeof(word));
96
        strncpy( word, ptr, MAX_DIGITS);
117
  length = strlen(ptr);
97
        length = strlen(ptr);
-
 
98
        if(length > MAX_DIGITS-1){
118
  if(length > MAX_DIGITS-1){fprintf(stdout,"ERROR string too large\n");exit(0);}
99
            fprintf(stdout,"ERROR string too large\n");
-
 
100
            exit(0);
-
 
101
        }
119
  /* reset counters */
102
        //reset counters
-
 
103
        powE = 0;
120
  powE = 0;pow10 = 0;idx1 = 0;idx2 = 0;i = 0;
104
        pow10 = 0;
-
 
105
        idx1 = 0;
-
 
106
        idx2 = 0;
-
 
107
        i = 0;
121
  for( i = 0; i < length ; i++){
108
        for( i = 0; i < length ; i++){
-
 
109
            if(powE > 1 ){
122
   if(powE > 1 ){ fprintf(stdout,"ERROR in syntax\n");exit(0);}
110
                fprintf(stdout,"ERROR in syntax\n");
-
 
111
                exit(0);
-
 
112
            }
-
 
113
            if( idx1 + idx2  >  MAX_DIGITS-1){
123
   if( idx1 + idx2  >  MAX_DIGITS-1){ fprintf(stdout,"ERROR string too large\n");exit(0);}
114
                fprintf(stdout,"ERROR string too large\n");
-
 
115
                exit(0);
-
 
116
            }
124
   switch( word[i] ){
117
            switch( word[i] ){
125
    case '+' : break; /* do not use 10^+2 */
118
                case '+' : break; /* do not use 10^+2 */
126
    case 'e' : powE++;break;
119
                case 'e' : powE++;break;
127
    case 'E' : powE++;break;
120
                case 'E' : powE++;break;
128
    case 'x' : pow10++;break;
121
                case 'x' : pow10++;break;
129
    case '*' : pow10++;break;
122
                case '*' : pow10++;break;
130
    /* word[2] = '^' --> 10^5 => 1.00*10^5 */
123
                case '^' : pow10=5;break;
131
    case '^' : if( i != 2 ){ pow10 = 5; }else{ idx1 = 1;idx2 = 0;pow10 = 4;} break;
124
                default  :
132
    default  : if( pow10 > 0 ){
125
                if( pow10 > 0 ){
133
                pow10++;
126
                    pow10++;
134
                if( pow10 > 4 ){ /*  *10^ = 4 chars */
127
                    if( pow10 > 4 ){ /*  *10^ = 4 chars */
135
                 exponent[idx2] = word[i];
128
                        exponent[idx2] = word[i];
136
                 idx2++;
129
                        idx2++;
137
                }
-
 
138
               }
130
                    }
139
               else
-
 
140
               {
-
 
141
                if(powE > 0){
-
 
142
                 exponent[idx2] = word[i];
-
 
143
                 idx2++;
-
 
144
                }
131
                }
145
                else
132
                else
146
                {
133
                {
-
 
134
                    if(powE > 0){
-
 
135
                        exponent[idx2] = word[i];
-
 
136
                        idx2++;
-
 
137
                    }
-
 
138
                    else
-
 
139
                    {
147
                 number[idx1] = word[i];
140
                        number[idx1] = word[i];
148
                 idx1++;
141
                        idx1++;
-
 
142
                    }
149
                }
143
                }
150
               }
-
 
151
               break;
144
                break;
152
   }
145
            }
153
  }
146
        }
154
  exponent[idx2] = '\0';
147
        exponent[idx2] = '\0';
155
  number[idx1] = '\0';
148
        number[idx1] = '\0';
156
  /* atof needs decimal point locale, like "C" */
149
        ascii_number = atof(number);
157
  setlocale(LC_NUMERIC, "C");
150
        if( ascii_number > 0 ){
158
  ascii_number = atof(number);
151
            ascii_number = ascii_number + correction;
-
 
152
        }
-
 
153
        else
-
 
154
        {
159
  if( ascii_number > 0 ){ ascii_number = ascii_number + correction;}else{ ascii_number = ascii_number - correction; }
155
            ascii_number = ascii_number - correction;
160
  if ( strcmp( w_use_comma , "1") == 0 ){ setlocale(LC_NUMERIC, LOCALE);sep = " "; }
156
        }
161
  if( powE == 1 || pow10> 0 ){
157
        if( powE == 1 || pow10> 0 ){
162
   if(cnt > 1){
158
            if(cnt > 1){
163
    fprintf( stdout , "%s%.*f*10^%s" ,sep, DECIMALS , ascii_number , exponent );
159
                fprintf( stdout , ",%.*f*10^%s" , DECIMALS , ascii_number , exponent );
164
   }
160
            }
165
   else
161
            else
166
   {
162
            {
167
    fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent );
163
                fprintf( stdout , "%.*f*10^%s" , DECIMALS , ascii_number , exponent );
168
   }
164
            }
169
  }
165
        }
170
  else
166
        else
171
  {
167
        {
172
   if(cnt > 1 ){
168
            if(cnt > 1 ){
173
    fprintf( stdout , "%s%.*f" ,sep, DECIMALS , ascii_number); 
169
                fprintf( stdout , ",%.*f" , DECIMALS , ascii_number);  
174
   }
170
            }
175
   else
171
            else
176
   {
172
            {
177
    fprintf( stdout , "%.*f" , DECIMALS , ascii_number);       
173
                fprintf( stdout , "%.*f" , DECIMALS , ascii_number);   
178
   }
174
            }
179
  }
175
        }
180
  cnt++;
176
        cnt++;
181
  ptr = strtok(NULL,",");
177
        ptr = strtok(NULL,",");
182
 }
178
    }
183
 fprintf(stdout,"\n");
179
    fprintf(stdout,"\n");
184
 return 0;
180
    return 0;
185
}
181
}
-
 
182