diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /pkg/utilities/nttools/tunits | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'pkg/utilities/nttools/tunits')
-rw-r--r-- | pkg/utilities/nttools/tunits/abrev.tab | 62 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/abrev.x | 113 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/convertcol.x | 68 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/factor.x | 125 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/mkpkg | 19 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/parseunits.com | 9 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/parseunits.x | 624 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/parseunits.y | 322 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/tuniterr.x | 24 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/tunits.h | 14 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/tunits.x | 112 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/unhash.x | 212 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/units.tab | 60 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/units.x | 162 | ||||
-rw-r--r-- | pkg/utilities/nttools/tunits/unstr.x | 381 |
15 files changed, 2307 insertions, 0 deletions
diff --git a/pkg/utilities/nttools/tunits/abrev.tab b/pkg/utilities/nttools/tunits/abrev.tab new file mode 100644 index 00000000..90b8b58c --- /dev/null +++ b/pkg/utilities/nttools/tunits/abrev.tab @@ -0,0 +1,62 @@ +# Abbreviation table for tunits task +# +# Many units have more than one name or abbreviation. This table lists +# the standard abbreviation for each set of units. The abbreviation is +# used internally when computing the conversion factor. Case is not +# significant in names and regular plurals (made by adding an "s") are +# converted to the singular. Names should contain only alphabetic characters. +# Blanks, underscores and digits are not allowed. +# +# name abbreviation +#---------------------------- +meter m +centimeter cm +kilometer km +millimeter mm +micrometer um +micron um +nanometer nm +metre m +centimetre cm +kilometre km +millimetre mm +micrometre um +nanometre nm +kilogram kg +gram g +gm g +milligram mg +second s +sec s +minute min +hour hr +year yr +radian rad +degree deg +arcminute amin +arcmin amin +arcsecond asec +arcsec asec +angstrom a +parsec pc +kiloparsec kpc +megaparsec mpc +hertz hz +kilohertz khz +megahertz mhz +gigahertz ghz +lightyear ly +newton n +joule j +watt w +calorie c +kilocalorie kc +inch in +inches in +foot ft +feet ft +ounce oz +pound lb +liter l +jansky jy +millijansky mjy diff --git a/pkg/utilities/nttools/tunits/abrev.x b/pkg/utilities/nttools/tunits/abrev.x new file mode 100644 index 00000000..f40ca944 --- /dev/null +++ b/pkg/utilities/nttools/tunits/abrev.x @@ -0,0 +1,113 @@ +include <tbset.h> +include "tunits.h" + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# FIND_ABREV -- Find the abbreviation for a units string + +int procedure find_abrev (ab, units, abrev, maxch) + +pointer ab # i: abbreviation hash table descriptor +char units[ARB] # i: units string +char abrev[ARB] # o: abbreviation string +int maxch # i: maximum length of abbreviation string +#-- +int status +pointer ptr + +int get_unhash() + +begin + status = get_unhash (ab, units, ptr) + if (status == NO) { + abrev[1] = EOS + } else { + call strcpy (Memc[ptr], abrev, maxch) + } + + return (status) +end + +# FREE_ABREV -- Free the abbreviation hash table + +procedure free_abrev (ab) + +pointer ab # i: abbreviation hash table descriptor +#-- +int index +pointer sp, keyword, value + +int each_unhash() + +begin + call smark (sp) + call salloc (keyword, LEN_UNIT, TY_CHAR) + + index = 0 + while (each_unhash (ab, index, Memc[keyword], + value, LEN_UNIT) != EOF) { + if (value != NULL) + call mfree (value, TY_CHAR) + } + + + call free_unhash (ab) + call sfree (sp) +end + +# READ_ABREV -- Read abbreviations from a table and load into a hash + +pointer procedure read_abrev (abrevtab) + +char abrevtab[ARB] # i: abbreviation table name +#-- +int irow, nrow +pointer tp, c1, c2, sp, units, abrev, ab + +string nocolumn "The abbreviation table must have two coulmns" + +int tbpsta() +pointer tbtopn(), tbcnum(), new_unhash() + +begin + # Dynamic memory for strings + + call smark (sp) + call salloc (units, LEN_UNIT, TY_CHAR) + + # Refer to columns numerically because + # this is supposed to be a text file + + tp = tbtopn (abrevtab, READ_ONLY, NULL) + c1 = tbcnum (tp, 1) + c2 = tbcnum (tp, 2) + + if (c1 == NULL || c2 == NULL) + call tuniterr (nocolumn, abrevtab) + + # Create hash + + nrow = tbpsta (tp, TBL_NROWS) + ab = new_unhash (nrow, LEN_UNIT) + + # Read each row into hash + + do irow = 1, nrow { + call malloc (abrev, LEN_UNIT, TY_CHAR) + + call tbegtt (tp, c1, irow, Memc[units], LEN_UNIT) + call tbegtt (tp, c2, irow, Memc[abrev], LEN_UNIT) + + call strlwr (Memc[units]) + call strlwr (Memc[abrev]) + + call add_unhash (ab, Memc[units], abrev) + } + + # Close table and free memory + + call tbtclo (tp) + call sfree (sp) + return (ab) +end diff --git a/pkg/utilities/nttools/tunits/convertcol.x b/pkg/utilities/nttools/tunits/convertcol.x new file mode 100644 index 00000000..976ea888 --- /dev/null +++ b/pkg/utilities/nttools/tunits/convertcol.x @@ -0,0 +1,68 @@ +include <tbset.h> + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# CONVERT_COL -- Convert the units of a table column + +procedure convert_col (tp, cp, newunits, factor) + +pointer tp # i: table descriptor +pointer cp # i: column descriptor +char newunits[ARB] # i: new column units +double factor # i: conversion factor +#-- +double value +int nrow, nelem, irow, nlen, ilen +pointer sp, buffer + +int tbpsta(), tbcigi(), tbagtd() + +begin + # Change column units + + call tbcnit (tp, cp, newunits) + + # Get column dimensions + + nrow = tbpsta (tp, TBL_NROWS) + nelem = tbcigi (cp, TBL_COL_LENDATA) + + # Allocate buffer to hold array elements + + call smark (sp) + call salloc (buffer, nelem, TY_DOUBLE) + + # Multiply column values by conversion factor + + if (nelem == 1) { + # Scalar column, use element get and put + + do irow = 1, nrow { + call tbegtd (tp, cp, irow, value) + if (! IS_INDEFD (value)) { + value = factor * value + call tbeptd (tp, cp, irow, value) + } + } + + } else { + # Array element, use array get and put + + do irow = 1, nrow { + nlen = tbagtd (tp, cp, irow, Memd[buffer], 1, nelem) + + do ilen = 0, nlen-1 { + if (! IS_INDEFD (Memd[buffer+ilen])) { + Memd[buffer+ilen] = factor * Memd[buffer+ilen] + } + } + + call tbaptd (tp, cp, irow, Memd[buffer], 1, nlen) + } + } + + call sfree (sp) +end + + diff --git a/pkg/utilities/nttools/tunits/factor.x b/pkg/utilities/nttools/tunits/factor.x new file mode 100644 index 00000000..3c9a91ac --- /dev/null +++ b/pkg/utilities/nttools/tunits/factor.x @@ -0,0 +1,125 @@ +include "tunits.h" + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# FIND_FACTOR -- Find conversion factor between two sets of units + +double procedure find_factor (ut, punit1, punit2, verbose) + +pointer ut # i: units hash descriptor +pointer punit1 # i: old set of units +pointer punit2 # i: new set of units +bool verbose # i: diagnostic message flag +#-- +double factor +pointer punit3, punit4, punit5 + +string noconvert "The old and new units are not compatible" + +pointer reduce_factor(), div_unstr() + +begin + # Reduce old and new units to a common form + + punit3 = reduce_factor (ut, punit1, verbose) + punit4 = reduce_factor (ut, punit2, verbose) + + # The conversion factor is the ratio of + # the two sets of units when in common form + + punit5 = div_unstr (punit3, punit4) + + # Check to make sure units actually have a common form + + if (TUN_UNPTR(punit5,1) != NULL) + call error (1, noconvert) + + factor = TUN_FACTOR (punit5) + + # Print conversion factor + if (verbose) { + call eprintf ("The conversion factor is %g\n") + call pargd (factor) + } + + # Free temporary units descriptors + + call free_unstr (punit3) + call free_unstr (punit4) + call free_unstr (punit5) + + return (factor) +end + +# REDUCE_FACTOR -- Reduce units descriptor to a common set of units (mks) + +pointer procedure reduce_factor (ut, punit, verbose) + +pointer ut # i: Units hash descriptor +pointer punit # i: Units string descriptor +bool verbose # i: diagnostic message flag +#-- +bool done +int idx +pointer sp, units, punit1, punit2, punit3, punit4 + +int find_units() +pointer copy_unstr(), pow_unstr(), mul_unstr() + +begin + # Allocate memory for units string + + call smark (sp) + call salloc (units, SZ_FNAME, TY_CHAR) + + # Loop until no more reductions can be performed + + punit1 = copy_unstr (punit) + + repeat { + if (verbose) { + call str_unstr (punit1, Memc[units], SZ_FNAME) + call eprintf ("%s") + call pargstr (Memc[units]) + } + + # Search for a reduction for any term + + done = true + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + if (find_units (ut, TUN_UNITS(punit1,idx), punit2) ==YES) { + # Reduction found. Raise conversion factor to + # degree of term in descriptor and then multiply + # the units by it + + punit3 = pow_unstr (punit2, TUN_POWER(punit1,idx)) + punit4 = mul_unstr (punit1, punit3) + + call free_unstr (punit1) + call free_unstr (punit3) + + punit1 = punit4 + done = false + break + } + } + + if (verbose) { + if (done) { + call eprintf ("\n") + } else { + call eprintf (" is \n") + } + } + } until (done) + + if (verbose) + call eprintf ("\n") + + call sfree (sp) + return (punit1) +end diff --git a/pkg/utilities/nttools/tunits/mkpkg b/pkg/utilities/nttools/tunits/mkpkg new file mode 100644 index 00000000..3ec0d98b --- /dev/null +++ b/pkg/utilities/nttools/tunits/mkpkg @@ -0,0 +1,19 @@ +# Update the tunits task in the ttools package library +# Author: Bernie Simon, 11-jan-99 + +$checkout libpkg.a ../ +$update libpkg.a +$checkin libpkg.a ../ +$exit + +libpkg.a: + abrev.x <tbset.h> "tunits.h" + convertcol.x <tbset.h> + factor.x "tunits.h" + parseunits.x <ctype.h> "parseunits.com" + tuniterr.x + tunits.x <tbset.h> "tunits.h" + unhash.x + units.x <tbset.h> "tunits.h" + unstr.x "tunits.h" + ; diff --git a/pkg/utilities/nttools/tunits/parseunits.com b/pkg/utilities/nttools/tunits/parseunits.com new file mode 100644 index 00000000..d5c5bf48 --- /dev/null +++ b/pkg/utilities/nttools/tunits/parseunits.com @@ -0,0 +1,9 @@ +# PARSEUNITS.COM -- Global variables used by parse_units + +common / parse / tun, abrev, tokbuf, nxttok, debug + +pointer tun # descriptor containing results of parse +pointer abrev # hash table of unit abbreviations +pointer tokbuf # buffer holding tokens parsed from units string +int nxttok # index to next free space in token buffer +int debug # debugging message flag diff --git a/pkg/utilities/nttools/tunits/parseunits.x b/pkg/utilities/nttools/tunits/parseunits.x new file mode 100644 index 00000000..1a420785 --- /dev/null +++ b/pkg/utilities/nttools/tunits/parseunits.x @@ -0,0 +1,624 @@ +include <ctype.h> + +#* B.Simon ?? original +# Phil Hodge 12-Jul-2005 add 'bool yydebug' and 'int get_token()' to +# parse_units + +define YYMAXDEPTH 32 +define YYOPLEN 1 +define yyparse unit_parse + +define SZ_SHORTSTR 31 + +define Y_WRONG 257 +define Y_DONE 258 +define Y_LPAR 259 +define Y_RPAR 260 +define Y_CU 261 +define Y_SQ 262 +define Y_ID 263 +define Y_NUM 264 +define Y_DIV 265 +define Y_MUL 266 +define Y_POW 267 +define yyclearin yychar = -1 +define yyerrok yyerrflag = 0 +define YYMOVE call amovi (Memi[$1], Memi[$2], YYOPLEN) +define YYERRCODE 256 + +# line 159 "parseunits.y" + + +# PARSE_UNITS -- Parse a units string into the internal format + +pointer procedure parse_units (ab, units) + +pointer ab # i: abbreviation hash table +char units[ARB] # i: expression to be parsed +#-- +include "parseunits.com" + +int len, fd +pointer sp + +string syntax "Syntax error in units" + +bool yydebug +int strlen(), stropen(), yyparse() +int get_token() +extern get_token + +begin + len = strlen (units) + 1 + fd = stropen (units, len, READ_ONLY) + + call smark (sp) + call salloc (tokbuf, SZ_FNAME, TY_CHAR) + + debug = NO + yydebug = (debug == YES) + nxttok = 0 + abrev = ab + tun = NULL + + if (yyparse (fd, yydebug, get_token) == ERR) + call tuniterr (syntax, units) + + call close (fd) + call sfree (sp) + return (tun) +end + +# GET_TOKEN -- Retrieve next token from units string + +int procedure get_token (fd, value) + +int fd # i: File containing expression to be lexed +pointer value # o: Address on parse stack to store token +#-- +include "parseunits.com" + +char ch +int type, index, powers[4] +pointer sp, typename, token + +string pownames "sq,square,cu,cubic" +data powers / Y_SQ, Y_SQ, Y_CU, Y_CU / + +bool streq() +int getc(), word_match() + +begin + call smark (sp) + call salloc (typename, SZ_FNAME, TY_CHAR) + + token = tokbuf + nxttok + Memi[value] = token + + repeat { + ch = getc (fd, ch) + } until (ch != ' ' && ch != '\t') + + if (ch == EOF) { + type = Y_DONE + call strcpy ("END", Memc[typename], SZ_FNAME) + + } else if (IS_ALPHA (ch)) { + type = Y_ID + call strcpy ("IDENT", Memc[typename], SZ_FNAME) + + while (IS_ALPHA (ch)) { + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + ch = getc (fd, ch) + } + call ungetc (fd, ch) + + Memc[tokbuf+nxttok] = EOS + index = word_match (Memc[token], pownames) + + if (index > 0) { + type = powers[index] + call strcpy ("POWER", Memc[typename], SZ_FNAME) + + } else if (streq (Memc[token], "per")) { + type = Y_DIV + call strcpy ("DIV", Memc[typename], SZ_FNAME) + } + + } else if (ch == '-' || IS_DIGIT (ch)) { + type = Y_NUM + call strcpy ("NUMBER", Memc[typename], SZ_FNAME) + + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + ch = getc (fd, ch) + + while (IS_DIGIT (ch)) { + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + ch = getc (fd, ch) + } + call ungetc (fd, ch) + + } else { + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + + switch (ch) { + case '*': + ch = getc (fd, ch) + if (ch == '*') { + type = Y_POW + call strcpy ("EXPON", Memc[typename], SZ_FNAME) + + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + } else { + type = Y_MUL + call strcpy ("MUL", Memc[typename], SZ_FNAME) + + call ungetc (fd, ch) + } + + case '/': + type = Y_DIV + call strcpy ("DIV", Memc[typename], SZ_FNAME) + + case '^': + type = Y_POW + call strcpy ("EXPON", Memc[typename], SZ_FNAME) + + default: + type = Y_WRONG + call strcpy ("ERROR", Memc[typename], SZ_FNAME) + } + } + + Memc[tokbuf+nxttok] = EOS + nxttok = nxttok + 1 + + if (debug == YES) { + call eprintf ("Token is %s [%s]\n") + if (Memc[token] == EOS) { + call pargstr ("EOS") + } else { + call pargstr (Memc[token]) + } + call pargstr (Memc[typename]) + } + + call sfree (sp) + return (type) +end +define YYNPROD 15 +define YYLAST 43 +# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + +# Parser for yacc output, translated to the IRAF SPP language. The contents +# of this file form the bulk of the source of the parser produced by Yacc. +# Yacc recognizes several macros in the yaccpar input source and replaces +# them as follows: +# A user suppled "global" definitions and declarations +# B parser tables +# C user supplied actions (reductions) +# The remainder of the yaccpar code is not changed. + +define yystack_ 10 # statement labels for gotos +define yynewstate_ 20 +define yydefault_ 30 +define yyerrlab_ 40 +define yyabort_ 50 + +define YYFLAG (-1000) # defs used in user actions +define YYERROR goto yyerrlab_ +define YYACCEPT return (OK) +define YYABORT return (ERR) + + +# YYPARSE -- Parse the input stream, returning OK if the source is +# syntactically acceptable (i.e., if compilation is successful), +# otherwise ERR. The parameters YYMAXDEPTH and YYOPLEN must be +# supplied by the caller in the %{ ... %} section of the Yacc source. +# The token value stack is a dynamically allocated array of operand +# structures, with the length and makeup of the operand structure being +# application dependent. + +int procedure yyparse (fd, yydebug, yylex) + +int fd # stream to be parsed +bool yydebug # print debugging information? +int yylex() # user-supplied lexical input function +extern yylex() + +short yys[YYMAXDEPTH] # parser stack -- stacks tokens +pointer yyv # pointer to token value stack +pointer yyval # value returned by action +pointer yylval # value of token +int yyps # token stack pointer +pointer yypv # value stack pointer +int yychar # current input token number +int yyerrflag # error recovery flag +int yynerrs # number of errors + +short yyj, yym # internal variables +pointer yysp, yypvt +short yystate, yyn +int yyxi, i +errchk salloc, yylex + + +include "parseunits.com" + +char units[SZ_FNAME] + +int num_unstr() +pointer mul_unstr(), div_unstr(), pow_unstr(), set_unstr() + +short yyexca[6] +data (yyexca(i),i= 1, 6) / -1, 1, 0, -1, -2, 0/ +short yyact[43] +data (yyact(i),i= 1, 8) / 23, 10, 11, 13, 13, 12, 11, 13/ +data (yyact(i),i= 9, 16) / 12, 11, 13, 17, 3, 24, 16, 4/ +data (yyact(i),i= 17, 24) / 22, 8, 9, 7, 4, 19, 8, 9/ +data (yyact(i),i= 25, 32) / 7, 8, 9, 7, 18, 2, 6, 5/ +data (yyact(i),i= 33, 40) / 1, 0, 14, 0, 15, 0, 0, 0/ +data (yyact(i),i= 41, 43) / 0, 20, 21/ +short yypact[25] +data (yypact(i),i= 1, 8) /-244,-1000,-257,-1000,-239,-236,-1000,-253/ +data (yypact(i),i= 9, 16) /-235,-242,-1000,-239,-239,-248,-260,-1000/ +data (yypact(i),i= 17, 24) /-251,-1000,-1000,-1000,-263,-264,-1000,-1000/ +data (yypact(i),i= 25, 25) /-1000/ +short yypgo[5] +data (yypgo(i),i= 1, 5) / 0, 32, 29, 31, 30/ +short yyr1[15] +data (yyr1(i),i= 1, 8) / 0, 1, 1, 2, 2, 2, 2, 2/ +data (yyr1(i),i= 9, 15) / 3, 3, 4, 4, 4, 4, 4/ +short yyr2[15] +data (yyr2(i),i= 1, 8) / 0, 2, 1, 3, 3, 3, 3, 1/ +data (yyr2(i),i= 9, 15) / 2, 1, 3, 2, 2, 2, 1/ +short yychk[25] +data (yychk(i),i= 1, 8) /-1000, -1, -2, 256, 259, -3, -4, 263/ +data (yychk(i),i= 9, 16) / 261, 262, 258, 266, 265, 267, -2, -4/ +data (yychk(i),i= 17, 24) / 267, 264, 263, 263, -2, -2, 264, 260/ +data (yychk(i),i= 25, 25) / 264/ +short yydef[25] +data (yydef(i),i= 1, 8) / 0, -2, 0, 2, 0, 7, 9, 14/ +data (yydef(i),i= 9, 16) / 0, 0, 1, 0, 0, 0, 0, 8/ +data (yydef(i),i= 17, 24) / 0, 11, 12, 13, 4, 5, 6, 3/ +data (yydef(i),i= 25, 25) / 10/ + +begin + call smark (yysp) + call salloc (yyv, (YYMAXDEPTH+2) * YYOPLEN, TY_STRUCT) + + # Initialization. The first element of the dynamically allocated + # token value stack (yyv) is used for yyval, the second for yylval, + # and the actual stack starts with the third element. + + yystate = 0 + yychar = -1 + yynerrs = 0 + yyerrflag = 0 + yyps = 0 + yyval = yyv + yylval = yyv + YYOPLEN + yypv = yylval + +yystack_ + # SHIFT -- Put a state and value onto the stack. The token and + # value stacks are logically the same stack, implemented as two + # separate arrays. + + if (yydebug) { + call printf ("state %d, char 0%o\n") + call pargs (yystate) + call pargi (yychar) + } + yyps = yyps + 1 + yypv = yypv + YYOPLEN + if (yyps > YYMAXDEPTH) { + call sfree (yysp) + call eprintf ("yacc stack overflow\n") + return (ERR) + } + yys[yyps] = yystate + YYMOVE (yyval, yypv) + +yynewstate_ + # Process the new state. + yyn = yypact[yystate+1] + + if (yyn <= YYFLAG) + goto yydefault_ # simple state + + # The variable "yychar" is the lookahead token. + if (yychar < 0) { + yychar = yylex (fd, yylval) + if (yychar < 0) + yychar = 0 + } + yyn = yyn + yychar + if (yyn < 0 || yyn >= YYLAST) + goto yydefault_ + + yyn = yyact[yyn+1] + if (yychk[yyn+1] == yychar) { # valid shift + yychar = -1 + YYMOVE (yylval, yyval) + yystate = yyn + if (yyerrflag > 0) + yyerrflag = yyerrflag - 1 + goto yystack_ + } + +yydefault_ + # Default state action. + + yyn = yydef[yystate+1] + if (yyn == -2) { + if (yychar < 0) { + yychar = yylex (fd, yylval) + if (yychar < 0) + yychar = 0 + } + + # Look through exception table. + yyxi = 1 + while ((yyexca[yyxi] != (-1)) || (yyexca[yyxi+1] != yystate)) + yyxi = yyxi + 2 + for (yyxi=yyxi+2; yyexca[yyxi] >= 0; yyxi=yyxi+2) { + if (yyexca[yyxi] == yychar) + break + } + + yyn = yyexca[yyxi+1] + if (yyn < 0) { + call sfree (yysp) + return (OK) # ACCEPT -- all done + } + } + + + # SYNTAX ERROR -- resume parsing if possible. + + if (yyn == 0) { + switch (yyerrflag) { + case 0, 1, 2: + if (yyerrflag == 0) { # brand new error + call eprintf ("syntax error\n") +yyerrlab_ + yynerrs = yynerrs + 1 + # fall through... + } + + # case 1: + # case 2: incompletely recovered error ... try again + yyerrflag = 3 + + # Find a state where "error" is a legal shift action. + while (yyps >= 1) { + yyn = yypact[yys[yyps]+1] + YYERRCODE + if ((yyn >= 0) && (yyn < YYLAST) && + (yychk[yyact[yyn+1]+1] == YYERRCODE)) { + # Simulate a shift of "error". + yystate = yyact[yyn+1] + goto yystack_ + } + yyn = yypact[yys[yyps]+1] + + # The current yyps has no shift on "error", pop stack. + if (yydebug) { + call printf ("error recovery pops state %d, ") + call pargs (yys[yyps]) + call printf ("uncovers %d\n") + call pargs (yys[yyps-1]) + } + yyps = yyps - 1 + yypv = yypv - YYOPLEN + } + + # ABORT -- There is no state on the stack with an error shift. +yyabort_ + call sfree (yysp) + return (ERR) + + + case 3: # No shift yet; clobber input char. + + if (yydebug) { + call printf ("error recovery discards char %d\n") + call pargi (yychar) + } + + if (yychar == 0) + goto yyabort_ # don't discard EOF, quit + yychar = -1 + goto yynewstate_ # try again in the same state + } + } + + + # REDUCE -- Reduction by production yyn. + + if (yydebug) { + call printf ("reduce %d\n") + call pargs (yyn) + } + yyps = yyps - yyr2[yyn+1] + yypvt = yypv + yypv = yypv - yyr2[yyn+1] * YYOPLEN + YYMOVE (yypv + YYOPLEN, yyval) + yym = yyn + + # Consult goto table to find next state. + yyn = yyr1[yyn+1] + yyj = yypgo[yyn+1] + yys[yyps] + 1 + if (yyj >= YYLAST) + yystate = yyact[yypgo[yyn+1]+1] + else { + yystate = yyact[yyj+1] + if (yychk[yystate+1] != -yyn) + yystate = yyact[yypgo[yyn+1]+1] + } + + # Perform action associated with the grammar rule, if any. + switch (yym) { + +case 1: +# line 28 "parseunits.y" +{ + # Normal exit. Return pointer to units structure + if (debug == YES) + call eprintf ("\n") + + tun = Memi[yypvt-YYOPLEN] + return (OK) + } +case 2: +# line 36 "parseunits.y" +{ + # Syntax error + if (debug == YES) + call eprintf ("\n") + + return (ERR) + } +case 3: +# line 45 "parseunits.y" +{ + # Parenthesized expression + Memi[yyval] = Memi[yypvt-2*YYOPLEN] + } +case 4: +# line 49 "parseunits.y" +{ + # Multiply two units expressions + Memi[yyval] = mul_unstr (Memi[yypvt-2*YYOPLEN], Memi[yypvt]) + call free_unstr (Memi[yypvt-2*YYOPLEN]) + call free_unstr (Memi[yypvt]) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 5: +# line 61 "parseunits.y" +{ + # Divide two units expressions + Memi[yyval] = div_unstr (Memi[yypvt-2*YYOPLEN], Memi[yypvt]) + call free_unstr (Memi[yypvt-2*YYOPLEN]) + call free_unstr (Memi[yypvt]) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 6: +# line 73 "parseunits.y" +{ + # Raise expression to a power + Memi[yyval] = pow_unstr (Memi[yypvt-2*YYOPLEN], num_unstr (Memc[Memi[yypvt]])) + call free_unstr (Memi[yypvt-2*YYOPLEN]) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 7: +# line 84 "parseunits.y" +{ + # List of terms + Memi[yyval] = Memi[yypvt] + } +case 8: +# line 89 "parseunits.y" +{ + # Implicit multiplication + Memi[yyval] = mul_unstr (Memi[yypvt-YYOPLEN], Memi[yypvt]) + call free_unstr (Memi[yypvt-YYOPLEN]) + call free_unstr (Memi[yypvt]) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 9: +# line 101 "parseunits.y" +{ + # Simple term + Memi[yyval] = Memi[yypvt] + } +case 10: +# line 106 "parseunits.y" +{ + # Raise units to a power + Memi[yyval] = set_unstr (abrev, Memc[Memi[yypvt-2*YYOPLEN]], + num_unstr (Memc[Memi[yypvt]])) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 11: +# line 117 "parseunits.y" +{ + # Implicitly raise to a power + Memi[yyval] = set_unstr (abrev, Memc[Memi[yypvt-YYOPLEN]], + num_unstr (Memc[Memi[yypvt]])) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 12: +# line 128 "parseunits.y" +{ + # Cubic prefix + Memi[yyval] = set_unstr (abrev, Memc[Memi[yypvt]], 3) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 13: +# line 138 "parseunits.y" +{ + # Square prefix + Memi[yyval] = set_unstr (abrev, Memc[Memi[yypvt]], 2) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } +case 14: +# line 148 "parseunits.y" +{ + # Simple name + Memi[yyval] = set_unstr (abrev, Memc[Memi[yypvt]], 1) + + if (debug == YES) { + call str_unstr (Memi[yyval], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } } + + goto yystack_ # stack new state and value +end diff --git a/pkg/utilities/nttools/tunits/parseunits.y b/pkg/utilities/nttools/tunits/parseunits.y new file mode 100644 index 00000000..088395ac --- /dev/null +++ b/pkg/utilities/nttools/tunits/parseunits.y @@ -0,0 +1,322 @@ +%{ +include <ctype.h> + +define YYMAXDEPTH 32 +define YYOPLEN 1 +define yyparse unit_parse + +define SZ_SHORTSTR 31 + +%L +include "parseunits.com" + +char units[SZ_FNAME] + +int num_unstr() +pointer mul_unstr(), div_unstr(), pow_unstr(), set_unstr() + +%} + +%token Y_WRONG Y_DONE Y_LPAR Y_RPAR Y_CU Y_SQ Y_ID Y_NUM + +%left Y_DIV +%left Y_MUL +%right Y_POW + +%% + +unit : expr Y_DONE { + # Normal exit. Return pointer to units structure + if (debug == YES) + call eprintf ("\n") + + tun = Memi[$1] + return (OK) + } + | error { + # Syntax error + if (debug == YES) + call eprintf ("\n") + + return (ERR) + } + ; + +expr : Y_LPAR expr Y_RPAR { + # Parenthesized expression + Memi[$$] = Memi[$1] + } + | expr Y_MUL expr { + # Multiply two units expressions + Memi[$$] = mul_unstr (Memi[$1], Memi[$3]) + call free_unstr (Memi[$1]) + call free_unstr (Memi[$3]) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | expr Y_DIV expr { + # Divide two units expressions + Memi[$$] = div_unstr (Memi[$1], Memi[$3]) + call free_unstr (Memi[$1]) + call free_unstr (Memi[$3]) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | expr Y_POW Y_NUM { + # Raise expression to a power + Memi[$$] = pow_unstr (Memi[$1], num_unstr (Memc[Memi[$3]])) + call free_unstr (Memi[$1]) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | termlist { + # List of terms + Memi[$$] = Memi[$1] + } + ; +termlist: termlist term { + # Implicit multiplication + Memi[$$] = mul_unstr (Memi[$1], Memi[$2]) + call free_unstr (Memi[$1]) + call free_unstr (Memi[$2]) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | term { + # Simple term + Memi[$$] = Memi[$1] + } + ; +term : Y_ID Y_POW Y_NUM { + # Raise units to a power + Memi[$$] = set_unstr (abrev, Memc[Memi[$1]], + num_unstr (Memc[Memi[$3]])) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | Y_ID Y_NUM { + # Implicitly raise to a power + Memi[$$] = set_unstr (abrev, Memc[Memi[$1]], + num_unstr (Memc[Memi[$2]])) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | Y_CU Y_ID { + # Cubic prefix + Memi[$$] = set_unstr (abrev, Memc[Memi[$2]], 3) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | Y_SQ Y_ID { + # Square prefix + Memi[$$] = set_unstr (abrev, Memc[Memi[$2]], 2) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + | Y_ID { + # Simple name + Memi[$$] = set_unstr (abrev, Memc[Memi[$1]], 1) + + if (debug == YES) { + call str_unstr (Memi[$$], units, SZ_FNAME) + call eprintf ("Units are %s\n") + call pargstr (units) + } + } + ; +%% + +# PARSE_UNITS -- Parse a units string into the internal format + +pointer procedure parse_units (ab, units) + +pointer ab # i: abbreviation hash table +char units[ARB] # i: expression to be parsed +#-- +include "parseunits.com" + +int len, fd +pointer sp + +string syntax "Syntax error in units" + +bool yydebug +int strlen(), stropen(), yyparse() +int get_token() +extern get_token + +begin + len = strlen (units) + 1 + fd = stropen (units, len, READ_ONLY) + + call smark (sp) + call salloc (tokbuf, SZ_FNAME, TY_CHAR) + + debug = NO + yydebug = (debug == YES) + nxttok = 0 + abrev = ab + tun = NULL + + if (yyparse (fd, yydebug, get_token) == ERR) + call tuniterr (syntax, units) + + call close (fd) + call sfree (sp) + return (tun) +end + +# GET_TOKEN -- Retrieve next token from units string + +int procedure get_token (fd, value) + +int fd # i: File containing expression to be lexed +pointer value # o: Address on parse stack to store token +#-- +include "parseunits.com" + +char ch +int type, index, powers[4] +pointer sp, typename, token + +string pownames "sq,square,cu,cubic" +data powers / Y_SQ, Y_SQ, Y_CU, Y_CU / + +bool streq() +int getc(), word_match() + +begin + call smark (sp) + call salloc (typename, SZ_FNAME, TY_CHAR) + + token = tokbuf + nxttok + Memi[value] = token + + repeat { + ch = getc (fd, ch) + } until (ch != ' ' && ch != '\t') + + if (ch == EOF) { + type = Y_DONE + call strcpy ("END", Memc[typename], SZ_FNAME) + + } else if (IS_ALPHA (ch)) { + type = Y_ID + call strcpy ("IDENT", Memc[typename], SZ_FNAME) + + while (IS_ALPHA (ch)) { + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + ch = getc (fd, ch) + } + call ungetc (fd, ch) + + Memc[tokbuf+nxttok] = EOS + index = word_match (Memc[token], pownames) + + if (index > 0) { + type = powers[index] + call strcpy ("POWER", Memc[typename], SZ_FNAME) + + } else if (streq (Memc[token], "per")) { + type = Y_DIV + call strcpy ("DIV", Memc[typename], SZ_FNAME) + } + + } else if (ch == '-' || IS_DIGIT (ch)) { + type = Y_NUM + call strcpy ("NUMBER", Memc[typename], SZ_FNAME) + + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + ch = getc (fd, ch) + + while (IS_DIGIT (ch)) { + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + ch = getc (fd, ch) + } + call ungetc (fd, ch) + + } else { + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + + switch (ch) { + case '*': + ch = getc (fd, ch) + if (ch == '*') { + type = Y_POW + call strcpy ("EXPON", Memc[typename], SZ_FNAME) + + Memc[tokbuf+nxttok] = ch + nxttok = nxttok + 1 + } else { + type = Y_MUL + call strcpy ("MUL", Memc[typename], SZ_FNAME) + + call ungetc (fd, ch) + } + + case '/': + type = Y_DIV + call strcpy ("DIV", Memc[typename], SZ_FNAME) + + case '^': + type = Y_POW + call strcpy ("EXPON", Memc[typename], SZ_FNAME) + + default: + type = Y_WRONG + call strcpy ("ERROR", Memc[typename], SZ_FNAME) + } + } + + Memc[tokbuf+nxttok] = EOS + nxttok = nxttok + 1 + + if (debug == YES) { + call eprintf ("Token is %s [%s]\n") + if (Memc[token] == EOS) { + call pargstr ("EOS") + } else { + call pargstr (Memc[token]) + } + call pargstr (Memc[typename]) + } + + call sfree (sp) + return (type) +end diff --git a/pkg/utilities/nttools/tunits/tuniterr.x b/pkg/utilities/nttools/tunits/tuniterr.x new file mode 100644 index 00000000..25a750c5 --- /dev/null +++ b/pkg/utilities/nttools/tunits/tuniterr.x @@ -0,0 +1,24 @@ +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# TUNITERR -- Print error message for tunits + +procedure tuniterr (errstr, errval) + +char errstr[ARB] # i: error message string +char errval[ARB] # i: value which caused error +#-- +pointer sp, errmsg + +begin + call smark (sp) + call salloc (errmsg, SZ_LINE, TY_CHAR) + + call sprintf (Memc[errmsg], SZ_LINE, "%s (%s)") + call pargstr (errstr) + call pargstr (errval) + + call error (1, Memc[errmsg]) + + call sfree (sp) +end diff --git a/pkg/utilities/nttools/tunits/tunits.h b/pkg/utilities/nttools/tunits/tunits.h new file mode 100644 index 00000000..f5c2162a --- /dev/null +++ b/pkg/utilities/nttools/tunits/tunits.h @@ -0,0 +1,14 @@ +# TUNITS.H -- Structure and constants used by tunits + +define MAXUNIT 8 +define LEN_UNIT 15 + +define LEN_TUNSTRUCT (SZ_DOUBLE+2*MAXUNIT) + +define TUN_FACTOR Memd[P2D($1)] # conversion factor +define TUN_UNPTR Memi[$1+SZ_DOUBLE+$2] # ptr to units string +define TUN_POWER Memi[$1+SZ_DOUBLE+MAXUNIT+$2] # units power + +define TUN_UNITS Memc[TUN_UNPTR($1,$2)] # units string + +define FINALS "m,kg,s,rad,hz" diff --git a/pkg/utilities/nttools/tunits/tunits.x b/pkg/utilities/nttools/tunits/tunits.x new file mode 100644 index 00000000..526bca11 --- /dev/null +++ b/pkg/utilities/nttools/tunits/tunits.x @@ -0,0 +1,112 @@ +include <tbset.h> +include "tunits.h" + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# TUNITS -- Convert table column from one set of units to another + +procedure tunits () + +#-- +pointer table # table name +pointer column # column name +pointer newunits # new column units +pointer oldunits # old column units +pointer abrevtab # table of unit abbreviations +pointer unittab # table of unit conversions +bool verbose # print diagnostic messages + +double factor +int type +pointer sp, tp, cp, ab, ut, punit1, punit2 + +string nocolumn "Column not found" +string unitblank "Units parameter is blank" +string notfloat "Table column is not floating point" + +bool clgetb(), isblank() +double find_factor() +int tbcigi() +pointer tbtopn(), read_abrev(), read_units(), parse_units() + +begin + # Allocate memory for temporary strings + + call smark (sp) + call salloc (table, SZ_FNAME, TY_CHAR) + call salloc (column, SZ_FNAME, TY_CHAR) + call salloc (newunits, SZ_FNAME, TY_CHAR) + call salloc (oldunits, SZ_FNAME, TY_CHAR) + call salloc (abrevtab, SZ_FNAME, TY_CHAR) + call salloc (unittab, SZ_FNAME, TY_CHAR) + + # Read required task parameters + + call clgstr ("table", Memc[table], SZ_FNAME) + call clgstr ("column", Memc[column], SZ_FNAME) + call clgstr ("newunits", Memc[newunits], SZ_FNAME) + call clgstr ("oldunits", Memc[oldunits], SZ_FNAME) + call clgstr ("abrevtab", Memc[abrevtab], SZ_FNAME) + call clgstr ("unittab", Memc[unittab], SZ_FNAME) + verbose = clgetb ("verbose") + + # Open table, find column + + tp = tbtopn (Memc[table], READ_WRITE, NULL) + call tbcfnd (tp, Memc[column], cp, 1) + if (cp == NULL) + call tuniterr (nocolumn, Memc[column]) + + # Read column units if old units are blank + + if (isblank (Memc[oldunits])) + call tbcigt (cp, TBL_COL_UNITS, Memc[oldunits], SZ_FNAME) + + call strlwr (Memc[oldunits]) + call strlwr (Memc[newunits]) + + # Check to see if units are not blank + + if (isblank (Memc[oldunits])) + call tuniterr (unitblank, "oldunits") + + if (isblank (Memc[newunits])) + call tuniterr (unitblank, "newunits") + + # Check to see if column is floating point + + type = tbcigi (cp, TBL_COL_DATATYPE) + if (type != TY_REAL && type != TY_DOUBLE) + call tuniterr (notfloat, Memc[column]) + + # Read units and abbreviation tables into hashes + + ab = read_abrev (Memc[abrevtab]) + ut = read_units (ab, Memc[unittab]) + + # Convert units to internal form + + punit1 = parse_units (ab, Memc[oldunits]) + punit2 = parse_units (ab, Memc[newunits]) + + # Find conversion factor between units + + factor = find_factor (ut, punit1, punit2, verbose) + + # Apply conversion factor to table column + + call convert_col (tp, cp, Memc[newunits], factor) + + # Close table and free allocated memory + + call tbtclo (tp) + + call free_abrev (ab) + call free_units (ut) + + call free_unstr (punit1) + call free_unstr (punit2) + + call sfree (sp) +end diff --git a/pkg/utilities/nttools/tunits/unhash.x b/pkg/utilities/nttools/tunits/unhash.x new file mode 100644 index 00000000..3ae9c24e --- /dev/null +++ b/pkg/utilities/nttools/tunits/unhash.x @@ -0,0 +1,212 @@ +# A set of procedures that implement a generic hash table. The hash table +# stores the key, plus a pointer to the value structure. It should be +# wrapped in a more specific set of calls that can read the value structure + +define LEN_UNHSTRUCT 5 + +define UNH_SIZE Memi[$1] +define UNH_NEXT Memi[$1+1] +define UNH_KEYBUF Memi[$1+2] +define UNH_VALBUF Memi[$1+3] +define UNH_STRBUF Memi[$1+4] + +define UNH_KEY Memi[UNH_KEYBUF($1)+$2] +define UNH_VALUE Memi[UNH_VALBUF($1)+$2] + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# ADD_UNHASH -- Add a new keyword and value to the hash table + +procedure add_unhash (hash, keyword, value) + +pointer hash # i: Descriptor of hash table +char keyword[ARB] # i: Keyword to add to hash table +pointer value # i: Value descriptor +#-- +int index, nc + +string duplicate "Cannot add duplicate keyword to hash table" + +int gstrcpy(), loc_unhash() + +begin + # Find where keyword should be inserted + + index = loc_unhash (hash, keyword) + + # Adding duplicate keywords is not allowed + + if (UNH_KEY(hash,index) != NULL) { + call tuniterr (duplicate, keyword) + + } else { + UNH_KEY(hash,index) = UNH_NEXT(hash) + UNH_VALUE(hash,index) = value + + nc = gstrcpy (keyword, Memc[UNH_NEXT(hash)], ARB) + UNH_NEXT(hash) = UNH_NEXT(hash) + nc + 1 + } +end + +# CALC_UNHASH -- Calculate hash index and step size from keyword + +procedure calc_unhash (hash, keyword, index, step) + +pointer hash # i: Descriptor of hash table +char keyword[ARB] # i: Keyword to search for in hash table +int index # o: Location to place keyword at in hash +int step # o: Step size in case location is filled +#-- +int ic + +begin + # Standard hash table function based on munging characters + + index = 0 + step = 0 + + for (ic = 1; keyword[ic] != EOS; ic = ic + 1) { + index = 2 * index + keyword[ic] + step = step + keyword[ic] + } + + # This line ensures the step size is odd + + step = step - mod (step, 2) + 1 +end + +# EACH_UNHASH -- Retrieve values from hash table serially + +int procedure each_unhash (hash, index, keyword, value, maxch) + +pointer hash # i: Descriptor of hash table +int index # u: Index of next slot in hash table to examine +char keyword[ARB] # o: Keyword name +pointer value # o: Keyword value +int maxch # i: Maximum length of keyword +#-- + +begin + while (index < UNH_SIZE(hash)) { + if (UNH_KEY(hash,index) != NULL) { + call strcpy (Memc[UNH_KEY(hash,index)], keyword, maxch) + value = UNH_VALUE(hash,index) + index = index + 1 + return (OK) + } + + index = index + 1 + } + + return (EOF) +end + +# FREE_UNHASH -- Free a hash table + +procedure free_unhash (hash) + +pointer hash # i: hash table descriptor +#-- + +begin + # This code assumes that all memory associated + # with the values has already been freed + + call mfree (UNH_STRBUF(hash), TY_CHAR) + call mfree (UNH_VALBUF(hash), TY_INT) + call mfree (UNH_KEYBUF(hash), TY_INT) + call mfree (hash, TY_INT) +end + +# GET_UNHASH -- Return a keyword's value from a hash + +int procedure get_unhash (hash, keyword, value) + +pointer hash # i: Descriptor of hash table +char keyword[ARB] # i: Keyword to add to hash table +pointer value # o: pointer to hash table value +#-- +int index, status + +int loc_unhash () + +begin + # The keyword is found if its slot is not null + + index = loc_unhash (hash, keyword) + + if (UNH_KEY(hash,index) == NULL) { + value = NULL + status = NO + } else { + value = UNH_VALUE(hash,index) + status = YES + } + + return (status) +end + +# LOC_UNHASH -- Return index of location where a key should be inserted + +int procedure loc_unhash (hash, keyword) + +pointer hash # i: Descriptor of hash table +char keyword[ARB] # i: Keyword to add to hash table +#-- +int index, step + +bool streq() + +begin + # Calculate initial guess at position in hash table + # and step size in case guessed position is already filled + + call calc_unhash (hash, keyword, index, step) + index = mod (index, UNH_SIZE(hash)) + + # Loop until an empty slot is found or the keyword is matched + + repeat { + if (UNH_KEY(hash,index) == NULL) { + break + + } else if (streq (Memc[UNH_KEY(hash,index)], keyword)) { + break + } + + index = mod (index + step, UNH_SIZE(hash)) + } + + return (index) +end + +# NEW_UNHASH -- Create a new hash table + +pointer procedure new_unhash (nkey, keysize) + +int nkey # i: number of keywords in the hash +int keysize # i: maximum length of a key +#-- +int size +pointer hash + +begin + # Find a power of two greater than the number of keywords + + for (size = 1; size < 2 * nkey; size = 2 * size) + ; + + # Allocate structure for hash and set initial values + + call malloc (hash, LEN_UNHSTRUCT, TY_INT) + call calloc (UNH_KEYBUF(hash), size, TY_INT) + call calloc (UNH_VALBUF(hash), size, TY_INT) + call malloc (UNH_STRBUF(hash), size*(keysize+1), TY_CHAR) + + UNH_SIZE(hash) = size + UNH_NEXT(hash) = UNH_STRBUF(hash) + + return (hash) +end + diff --git a/pkg/utilities/nttools/tunits/units.tab b/pkg/utilities/nttools/tunits/units.tab new file mode 100644 index 00000000..4d2c1f9c --- /dev/null +++ b/pkg/utilities/nttools/tunits/units.tab @@ -0,0 +1,60 @@ +# Conversion factors for tunits task +# +# Read this table as "There are <factor> <from> in a <to>." +# For example, "There are 100 centimeters in a meter." +# The last column, swap, does not change the sense of the sentence +# but does change the direction that the conversion is applied, +# For example, "60 seconds in a minute" is actually a conversion +# from minutes to seconds because swap is yes. Unit conversions +# should set swap to yes when the desired conversion is not an exact +# value, but its inverse is. Only one conversion is allowed per +# unit, which simplifies the program logic considerably. Conversions +# should be chosen so that they ultimately resolve to MKS units. To +# prevent endless loops conversions from the fundamental units are +# checked for and forbidden. However, the program does not check for +# other loops, so be careful when adding new conversions! +# +# factor from to swap? +#---------------------------------------------------- +100 centimeter meter no +1e-3 kilometer meter no +1e3 millimeter meter no +1e6 micron meter no +1e9 nanometer meter no +1e10 angstrom meter no +1e3 gram kilogram no +1e6 milligram kilogram no +60 second minute yes +60 minute hour yes +24 hour day yes +365.2421897 day year yes +57.2957795131 degree radian no +60 arcminute degree no +60 arcsecond arcminute no +1.4959787066e11 meter au yes +206264.806247 au parsec yes +1e3 parsec kiloparsec yes +1e6 parsec megaparsec yes +9.46073047e15 meter lightyear yes +1e3 liter m^3 no +1 newton kg*m/s^2 no +1 joule kg*m^2/s^2 no +1 watt kg*m^2/s^3 no +1 dyne gm*cm/s^2 no +1 erg gm*cm^2/s^2 no +2.54 centimeter inch yes +12 inch foot yes +5280 foot mile yes +16 ounce pound no +0.45359237 pound kilogram no +1054.4 btu joule no +4.184 calorie joule no +1e-3 kilocalorie calorie no +6.24150648e18 ev joule no +1e-3 kev ev no +1e-6 mev ev no +1e23 jansky erg/s*cm^2*hz no +1e3 millijansky jansky no +1e-3 kilohertz hertz no +1e-6 megahertz hertz no +1e-9 gigahertz hertz no diff --git a/pkg/utilities/nttools/tunits/units.x b/pkg/utilities/nttools/tunits/units.x new file mode 100644 index 00000000..6f4374df --- /dev/null +++ b/pkg/utilities/nttools/tunits/units.x @@ -0,0 +1,162 @@ +include <tbset.h> +include "tunits.h" + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# FIND_UNITS -- Find the conversion factor for a set of units + +int procedure find_units (ut, units, punit) + +pointer ut # i: units hash table descriptor +char units[ARB] # i: units string +pointer punit # o: conversion factor as units structure +#-- +int get_unhash() + +begin + return (get_unhash (ut, units, punit)) +end + +# FREE_UNITS -- Free the abbreviation hash table + +procedure free_units (ut) + +pointer ut # i: units hash table descriptor +#-- +int index +pointer sp, units, punit + +int each_unhash() + +begin + call smark (sp) + call salloc (units, LEN_UNIT, TY_CHAR) + + index = 0 + while (each_unhash (ut, index, Memc[units], + punit, LEN_UNIT) != EOF) { + if (punit != NULL) + call free_unstr (punit) + } + + call free_unhash (ut) + call sfree (sp) +end + +# READ_UNITS -- Read units conversions from a table and load into a hash + +pointer procedure read_units (ab, unittab) + +pointer ab # i: abbreviation table descriptor +char unittab[ARB] # i: units conversion table name +#-- +bool swap, verbose +double factor +int irow, nrow +pointer sp, temp, oldunits, newunits +pointer tp, c1, c2, c3, c4 +pointer ut, punit1, punit2, punit3 + +data verbose / false / + +string nocolumn "The units conversion table must have four columns" +string badfactor "Error in units table: factor must be greater than zero" +string nofinal "Error in units table: conversion from final units not allowed" + +int tbpsta(), word_match() +pointer tbtopn(), tbcnum(), new_unhash() +pointer parse_units(), div_unstr() + +begin + # Dynamic memory for strings + + call smark (sp) + call salloc (temp, SZ_FNAME, TY_CHAR) + call salloc (oldunits, SZ_FNAME, TY_CHAR) + call salloc (newunits, SZ_FNAME, TY_CHAR) + + # Refer to columns numerically because + # this is supposed to be a text file + + tp = tbtopn (unittab, READ_ONLY, NULL) + c1 = tbcnum (tp, 1) + c2 = tbcnum (tp, 2) + c3 = tbcnum (tp, 3) + c4 = tbcnum (tp, 4) + + if (c1 == NULL || c2 == NULL || c3 == NULL || c4 == NULL) + call tuniterr (nocolumn, unittab) + + # Create hash + + nrow = tbpsta (tp, TBL_NROWS) + ut = new_unhash (nrow, LEN_UNIT) + + # Read each row into hash + + do irow = 1, nrow { + # Read table columns + + call tbegtd (tp, c1, irow, factor) + call tbegtt (tp, c2, irow, Memc[oldunits], SZ_FNAME) + call tbegtt (tp, c3, irow, Memc[newunits], SZ_FNAME) + call tbegtb (tp, c4, irow, swap) + + # Check conversion factor + + if (factor <= 0.0) + call tuniterr (badfactor, Memc[oldunits]) + + # Swap the units string and the conversion factor + + if (swap) { + call strcpy (Memc[oldunits], Memc[temp], SZ_FNAME) + call strcpy (Memc[newunits], Memc[oldunits], SZ_FNAME) + call strcpy (Memc[temp], Memc[newunits], SZ_FNAME) + } + + # Check to see that old units aren't one of the final forms + + if (word_match (Memc[oldunits], FINALS) != 0) + call tuniterr (nofinal, Memc[oldunits]) + + # Parse the old and new units strings + + call strlwr (Memc[newunits]) + punit1 = parse_units (ab, Memc[newunits]) + + call strlwr (Memc[oldunits]) + punit2 = parse_units (ab, Memc[oldunits]) + + # The conversion factor is ratio of the two sets of units + + punit3 = div_unstr (punit1, punit2) + if (swap) { + TUN_FACTOR(punit3) = factor + } else { + TUN_FACTOR(punit3) = 1.0 / factor + } + + if (verbose) { + call str_unstr (punit3, Memc[temp], SZ_FNAME) + + call eprintf ("The conversion factor is %s\n\n") + call pargstr (Memc[temp]) + } + + # Add it to the hash + + call abrev_unstr (ab, Memc[oldunits], Memc[temp], SZ_FNAME) + call add_unhash (ut, Memc[temp], punit3) + + call free_unstr (punit1) + call free_unstr (punit2) + } + + # Close table and free memory + + call tbtclo (tp) + call sfree (sp) + return (ut) +end diff --git a/pkg/utilities/nttools/tunits/unstr.x b/pkg/utilities/nttools/tunits/unstr.x new file mode 100644 index 00000000..80bd65ba --- /dev/null +++ b/pkg/utilities/nttools/tunits/unstr.x @@ -0,0 +1,381 @@ +include "tunits.h" + +#* HISTORY * +#* B.Simon 07-Jan-99 Original + +# ABREV_UNSTR -- Replace units string with its abbreviation + +procedure abrev_unstr (ab, instr, outstr, maxch) + +pointer ab # i: abbreviation hash descriptor +char instr[ARB] # i: string to be abbreviated +char outstr[ARB] # o: abbreviated string +int maxch # i: max length of abbreviated string +#-- +int nc +pointer sp, temp + +int gstrcpy(), find_abrev () + +begin + if (find_abrev (ab, instr, outstr, maxch) == YES) + return + + call smark (sp) + call salloc (temp, LEN_UNIT, TY_CHAR) + + nc = gstrcpy (instr, Memc[temp], LEN_UNIT) + if (nc == 1 || instr[nc] != 's') { + call strcpy (instr, outstr, maxch) + + } else { + Memc[temp+nc-1] = EOS + if (find_abrev (ab, Memc[temp], outstr, maxch) == NO) + call strcpy (Memc[temp], outstr, maxch) + } + + call sfree (sp) +end + +# COPY_UNSTR -- Copy a units descriptor + +pointer procedure copy_unstr (punit1) + +pointer punit1 # i: units descriptor to be copied +#-- +int idx +pointer punit2 + +begin + # Allocate structure to hold units + + call calloc (punit2, LEN_TUNSTRUCT, TY_INT) + + # Copy numeric factor + + TUN_FACTOR(punit2) = TUN_FACTOR(punit1) + + # Copy units and their powers + + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + call malloc (TUN_UNPTR(punit2,idx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit1,idx), TUN_UNITS(punit2,idx), + LEN_UNIT) + + TUN_POWER(punit2,idx) = TUN_POWER(punit1,idx) + } + + return (punit2) +end +# DIV_UNSTR -- Divide one set of units by another + +pointer procedure div_unstr (punit1, punit2) + +pointer punit1 # i: descriptor for first set of units +pointer punit2 # i: descriptor for second set of units +#-- +int idx, jdx, kdx, power +pointer punit3 + +int find_unstr() + +begin + # Allocate structure to hold units + + call calloc (punit3, LEN_TUNSTRUCT, TY_INT) + + # Compute the new factor + + TUN_FACTOR(punit3) = TUN_FACTOR(punit1) / TUN_FACTOR(punit2) + + # Find units in both descriptors and subtract their powers + + jdx = 1 + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + kdx = find_unstr (punit2, TUN_UNITS(punit1, idx)) + if (kdx == 0) + next + + power = TUN_POWER(punit1,idx) - TUN_POWER(punit2,kdx) + if (power == 0) + next + + call malloc (TUN_UNPTR(punit3,jdx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit1,idx), TUN_UNITS(punit3,jdx), + LEN_UNIT) + + TUN_POWER(punit3,jdx) = power + jdx = jdx + 1 + + } + + # Find units only in a single descriptor and add them to the + # new descriptor + + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + if (find_unstr (punit2, TUN_UNITS(punit1, idx)) == 0) { + call malloc (TUN_UNPTR(punit3,jdx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit1,idx), TUN_UNITS(punit3,jdx), + LEN_UNIT) + + TUN_POWER(punit3,jdx) = TUN_POWER(punit1,idx) + jdx = jdx + 1 + } + } + + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit2,idx) == NULL) + break + + if (find_unstr (punit1, TUN_UNITS(punit2, idx)) == 0) { + call malloc (TUN_UNPTR(punit3,jdx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit2,idx), TUN_UNITS(punit3,jdx), + LEN_UNIT) + + TUN_POWER(punit3,jdx) = - TUN_POWER(punit2,idx) + jdx = jdx + 1 + } + } + + return (punit3) +end + +# FIND_UNSTR -- Find location of units string in descriptor + +int procedure find_unstr (punit, units) + +pointer punit # i: units descriptor +char units[ARB] # i: units string to search for +#-- +int idx +bool streq() + +begin + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit,idx) == NULL) + break + + if (streq (TUN_UNITS(punit,idx), units)) + return (idx) + } + + return (0) +end + +# FREE_UNSTR -- Release memory used by a units descriptor + +procedure free_unstr (punit) + +pointer punit # i: units descriptor +#-- +int idx + +begin + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit,idx) == NULL) + break + + call mfree (TUN_UNPTR(punit,idx), TY_CHAR) + } + + call mfree (punit, TY_INT) +end + +# MUL_UNSTR -- Multiply two sets of units together + +pointer procedure mul_unstr (punit1, punit2) + +pointer punit1 # i: descriptor for first set of units +pointer punit2 # i: descriptor for second set of units +#-- +int idx, jdx, kdx, power +pointer punit3 + +int find_unstr() + +begin + # Allocate structure to hold units + + call calloc (punit3, LEN_TUNSTRUCT, TY_INT) + + # Compute the new factor + + TUN_FACTOR(punit3) = TUN_FACTOR(punit1) * TUN_FACTOR(punit2) + + # Find units in both descriptors and add their powers + + jdx = 1 + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + kdx = find_unstr (punit2, TUN_UNITS(punit1, idx)) + if (kdx == 0) + next + + power = TUN_POWER(punit1,idx) + TUN_POWER(punit2,kdx) + if (power == 0) + next + + call malloc (TUN_UNPTR(punit3,jdx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit1,idx), TUN_UNITS(punit3,jdx), + LEN_UNIT) + + TUN_POWER(punit3,jdx) = power + jdx = jdx + 1 + + } + + # Find units only in a single descriptor and add them to the + # new descriptor + + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + if (find_unstr (punit2, TUN_UNITS(punit1, idx)) == 0) { + call malloc (TUN_UNPTR(punit3,jdx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit1,idx), TUN_UNITS(punit3,jdx), + LEN_UNIT) + + TUN_POWER(punit3,jdx) = TUN_POWER(punit1,idx) + jdx = jdx + 1 + } + } + + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit2,idx) == NULL) + break + + if (find_unstr (punit1, TUN_UNITS(punit2, idx)) == 0) { + call malloc (TUN_UNPTR(punit3,jdx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit2,idx), TUN_UNITS(punit3,jdx), + LEN_UNIT) + + TUN_POWER(punit3,jdx) = TUN_POWER(punit2,idx) + jdx = jdx + 1 + } + } + + return (punit3) +end + +# NUM_UNSTR -- Convert a token to an integer + +int procedure num_unstr (value) + +char value[ARB] # i: string containing token value +#-- +int ic, nc, num + +int ctoi() + +begin + ic = 1 + nc = ctoi (value, ic, num) + return (num) +end + +# POW_UNSTR -- Raise a set of units to an integer power + +pointer procedure pow_unstr (punit1, power) + +pointer punit1 # i: units descriptor to be raised to power +int power +#-- +int idx +pointer punit2 + +begin + # Allocate structure to hold units + + call calloc (punit2, LEN_TUNSTRUCT, TY_INT) + + # Compute the new factor + + TUN_FACTOR(punit2) = TUN_FACTOR(punit1) ** power + + # Find units in both descriptors and add their powers + + if (power != 0) { + for (idx = 1; idx <= MAXUNIT; idx = idx + 1) { + if (TUN_UNPTR(punit1,idx) == NULL) + break + + call malloc (TUN_UNPTR(punit2,idx), LEN_UNIT, TY_CHAR) + call strcpy (TUN_UNITS(punit1,idx), TUN_UNITS(punit2,idx), + LEN_UNIT) + + TUN_POWER(punit2,idx) = TUN_POWER(punit1,idx) * power + } + } + + return (punit2) +end + +# SET_UNSTR -- Make a new units description from a units string and its power + +pointer procedure set_unstr (ab, units, power) + +pointer ab # i: hash of units abbreviations +char units[ARB] # i: units string +int power # i: power of the units +#-- +pointer punit + +begin + # Allocate structure to hold units + + call calloc (punit, LEN_TUNSTRUCT, TY_INT) + call malloc (TUN_UNPTR(punit,1), LEN_UNIT, TY_CHAR) + + # Set the first slot in the structure to hold the string + # and power passed to this procedure + + TUN_FACTOR(punit) = 1.0 + TUN_POWER(punit,1) = power + call abrev_unstr (ab, units, TUN_UNITS(punit,1), LEN_UNIT) + + return (punit) +end + +# STR_UNSTR -- Convert units structure into a string + +procedure str_unstr (punit, str, maxch) + +pointer punit # i: units descriptor +char str[ARB] # o: string representation of units +int maxch # i: max length of string +#-- +int ic, idx + +int strlen(), gstrcpy(), itoc() + +begin + call sprintf (str, maxch, "%g") + call pargd (TUN_FACTOR(punit)) + + ic = strlen (str) + 1 + + do idx = 1, MAXUNIT { + if (TUN_UNPTR(punit,idx) == NULL) + break + + ic = ic + gstrcpy ("*", str[ic], maxch-ic+1) + ic = ic + gstrcpy (TUN_UNITS(punit,idx), str[ic], maxch+ic-1) + + if (TUN_POWER(punit,idx) != 1) { + ic = ic + gstrcpy ("^", str[ic], maxch-ic+1) + ic = ic + itoc (TUN_POWER(punit,idx), str[ic], maxch-ic+1) + } + } +end |