swissChili | 729acd5 | 2024-03-05 11:52:45 -0500 | [diff] [blame^] | 1 | /* |
| 2 | * units, a program for units conversion |
| 3 | * Copyright (C) 1996, 1997, 1999, 2000, 2001, 2014, 2017 |
| 4 | * Free Software Foundation, Inc |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify |
| 7 | * it under the terms of the GNU General Public License as published by |
| 8 | * the Free Software Foundation; either version 3 of the License, or |
| 9 | * (at your option) any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, |
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | * GNU General Public License for more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License |
| 17 | * along with this program; if not, write to the Free Software |
| 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 | * |
| 20 | * This program was written by Adrian Mariano (adrianm@gnu.org) |
| 21 | */ |
| 22 | |
| 23 | #include <math.h> |
| 24 | #include <errno.h> |
| 25 | |
| 26 | /* Apparently popen and pclose require leading _ under windows */ |
| 27 | #if defined(_MSC_VER) || defined(__MINGW32__) |
| 28 | # define popen _popen |
| 29 | # define pclose _pclose |
| 30 | #endif |
| 31 | |
| 32 | |
| 33 | #ifdef NO_ISFINITE |
| 34 | # if defined _WIN32 && defined _MSC_VER |
| 35 | # define isfinite(x) (!_isnan(x) && _finite(x)) |
| 36 | # else |
| 37 | # define isfinite(x) ( -DBL_MAX <= (x) && (x) <= DBL_MAX ) |
| 38 | # endif |
| 39 | #endif |
| 40 | |
| 41 | #ifdef STRINGS_H |
| 42 | # include <strings.h> |
| 43 | #else |
| 44 | # include <string.h> |
| 45 | #endif |
| 46 | |
| 47 | #ifndef NO_STDLIB_H |
| 48 | # include <stdlib.h> |
| 49 | #else |
| 50 | char *malloc(), *realloc(), *getenv(); |
| 51 | #endif |
| 52 | |
| 53 | #ifndef strchr |
| 54 | # ifdef NO_STRCHR |
| 55 | # define strchr(a,b) index((a),(b)) |
| 56 | # else |
| 57 | char *strchr(); |
| 58 | # endif |
| 59 | #endif /* !strchr */ |
| 60 | |
| 61 | #define E_NORMAL 0 |
| 62 | #define E_PARSE 1 |
| 63 | #define E_PRODOVERFLOW 2 |
| 64 | #define E_REDUCE 3 |
| 65 | #define E_CIRCULARDEF 4 |
| 66 | #define E_BADSUM 5 |
| 67 | #define E_NOTANUMBER 6 |
| 68 | #define E_NOTROOT 7 |
| 69 | #define E_UNKNOWNUNIT 8 |
| 70 | #define E_FUNC 9 /* If errno is set after calling a function */ |
| 71 | #define E_BADFUNCTYPE 10 |
| 72 | #define E_BADFUNCARG 11 |
| 73 | #define E_NOTINDOMAIN 12 |
| 74 | #define E_BADFUNCDIMEN 13 |
| 75 | #define E_NOINVERSE 14 |
| 76 | #define E_PARSEMEM 15 |
| 77 | #define E_FUNARGDEF 16 |
| 78 | #define E_FILE 17 |
| 79 | #define E_BADFILE 18 |
| 80 | #define E_MEMORY 19 |
| 81 | #define E_BADNUM 20 |
| 82 | #define E_UNITEND 21 |
| 83 | #define E_LASTUNSET 22 |
| 84 | #define E_IRRATIONAL_EXPONENT 23 |
| 85 | #define E_BASE_NOTROOT 24 |
| 86 | #define E_DIMEXPONENT 25 |
| 87 | #define E_NOTAFUNC 26 |
| 88 | #define E_OVERFLOW 27 |
| 89 | #define E_UNDERFLOW 28 |
| 90 | |
| 91 | extern char *errormsg[]; |
| 92 | |
| 93 | /* |
| 94 | Data type used to store a single unit being operated on. |
| 95 | |
| 96 | The numerator and denominator arrays contain lists of units |
| 97 | (strings) which are terminated by a null pointer. The special |
| 98 | string NULLUNIT is used to mark blank units that occur in the |
| 99 | middle of the list. |
| 100 | */ |
| 101 | |
| 102 | extern char *NULLUNIT; |
| 103 | |
| 104 | #define MAXSUBUNITS 100 /* Size of internal unit reduction buffer */ |
| 105 | |
| 106 | struct unittype { |
| 107 | char *numerator[MAXSUBUNITS]; |
| 108 | char *denominator[MAXSUBUNITS]; |
| 109 | double factor; |
| 110 | }; |
| 111 | |
| 112 | |
| 113 | struct functype { |
| 114 | char *param; |
| 115 | char *def; |
| 116 | char *dimen; |
| 117 | double *domain_min, *domain_max; |
| 118 | int domain_min_open, domain_max_open; |
| 119 | }; |
| 120 | |
| 121 | struct pair { |
| 122 | double location, value; |
| 123 | }; |
| 124 | |
| 125 | struct func { |
| 126 | char *name; |
| 127 | struct functype forward; |
| 128 | struct functype inverse; |
| 129 | struct pair *table; |
| 130 | int tablelen; |
| 131 | char *tableunit; |
| 132 | struct func *next; |
| 133 | int skip_error_check; /* do not check for errors when running units -c */ |
| 134 | int linenumber; |
| 135 | char *file; /* file where defined */ |
| 136 | }; |
| 137 | |
| 138 | struct parseflag { |
| 139 | int oldstar; /* Does '*' have higher precedence than '/' */ |
| 140 | int minusminus; /* Does '-' character give subtraction */ |
| 141 | }; |
| 142 | extern struct parseflag parserflags; |
| 143 | |
| 144 | extern struct unittype *parameter_value; |
| 145 | extern char *function_parameter; |
| 146 | |
| 147 | extern int lastunitset; |
| 148 | extern struct unittype lastunit; |
| 149 | |
| 150 | void *mymalloc(int bytes, const char *mesg); |
| 151 | int hassubscript(const char *str); |
| 152 | void initializeunit(struct unittype *theunit); |
| 153 | void freeunit(struct unittype *theunit); |
| 154 | void unitcopy(struct unittype *dest,struct unittype *src); |
| 155 | int divunit(struct unittype *left, struct unittype *right); |
| 156 | void invertunit(struct unittype *theunit); |
| 157 | int multunit(struct unittype *left, struct unittype *right); |
| 158 | int expunit(struct unittype *theunit, int power); |
| 159 | int addunit(struct unittype *unita, struct unittype *unitb); |
| 160 | int rootunit(struct unittype *inunit,int n); |
| 161 | int unitpower(struct unittype *base, struct unittype *exponent); |
| 162 | char *dupstr(const char *str); |
| 163 | char *dupnstr(const char *string, int length); |
| 164 | int unit2num(struct unittype *input); |
| 165 | struct func *fnlookup(const char *str); |
| 166 | int evalfunc(struct unittype *theunit, struct func *infunc, int inverse, |
| 167 | int allerror); |
| 168 | int parseunit(struct unittype *output, const char *input, char **errstr, |
| 169 | int *errloc); |
| 170 | |