// I'm sorry, it is one of my first programs in C++. // // So it looks a little erratic. // // // // You've been warned ;) // // // // Newly updated, code ported to Linux and updated for CGI // #include #include #include #include #include // set up the filename for the file with unit descriptions #define INIFILENAME "/usr/share/ucalc.ini" //If this is defined, generate code for a CGI script: take input from querystring, output as HTML. //#define IS_CGI #ifdef IS_CGI #define LOGFILENAME "ucalc.log" #include "cgi.h" #include "log.c" #endif typedef struct { char utype[10]; // unit type (length, volume...) char uname[20]; // unit name char ushrt[10]; // unit shortcut double conv; // multiply with... double convadd; // ...and add... double rangel; // do not show if result lower than this double rangeh; // do not show if result higher than this int metric; // is metric? int invert; // invert - for freq/vawelength etc. int allowpref[16]; // flags of metric prefixes } METRICUNIT; typedef struct { char prefchar; // prefix character double order; // exponent double orders; // size of subrange } METRICPREFIX; const METRICPREFIX prefix[14]= {{'a',1e-18,1e3}, {'f',1e-15,1e3}, {'p',1e-12,1e3}, {'n',1e-9 ,1e3}, {'u',1e-6 ,1e3}, {'m',1e-3 ,1e3}, {'c',1e-2 ,1e2}, {'d',1e-1 ,1e1}, {' ',1 ,1e3}, {'h',1e2 ,1e2}, {'k',1e3 ,1e3}, {'M',1e6 ,1e3}, {'G',1e9 ,1e3}, {'T',1e12 ,1e3}}; char*strupr(char*s) { char*sp;sp=s; while(s[0]){s[0]=toupper(s[0]);s++;} return s;} char*strlwr(char*s) { char*sp;sp=s; while(s[0]){s[0]=tolower(s[0]);s++;} return s;} /* HELP OUTPUT BEGINS HERE */ void printhelpunits(char*paramstr1,char*paramstr2) { char s[250]; char unittype[10]; FILE *f; METRICUNIT m; int n,t; #ifdef IS_CGI dedicate(); printf("

\n

\n");
#endif
//      f=fopen(inifile,"r");
      f=fopen(INIFILENAME,"r");
      if (!f) {printf("\nINIfile open error on \"%s\"!\n",INIFILENAME);return;}
      if (strcasecmp(paramstr2,"?")==0) printf("\nAvailable typedefs:\n");
#ifdef IS_CGI
                                  else printf("\n
  Available units:\n");
#else
                                  else printf("\n  Available units:\n");
#endif
      strcpy(unittype,"");
      seeksection(f,"[unitdef]");
      while (!feof(f))
       {fgets(s,250,f);
        if (readinirow(&m,s))
         if ((strcmp(paramstr2,"")==0)||(strcasecmp(paramstr2,m.utype)==0)||(strcasecmp(paramstr2,"?")==0))
         { if (strcasecmp(unittype,m.utype)!=0)
            {if (strcmp(paramstr2,"?")==0) printf("  %s\n",m.utype);
#ifdef IS_CGI
                                        else printf("\n  %s:\n",m.utype);
#else
                                        else printf("\n  %s:\n",m.utype);
#endif
             strcpy(unittype,m.utype);
             }
           if (strcmp(paramstr2,"?")!=0)
           {
           printf("    %-20s ",m.uname);
           for (t=0,n=0;t<14;t++)
             if (m.allowpref[t])
             {if(n) printf(", ");
              //if (prefix[t].prefchar=='u') printf("µ"); else
              if (prefix[t].prefchar!=' ') printf("%c",prefix[t].prefchar);
              printf("%s",m.ushrt);n=1;}
           printf("\n");}
         }}
#ifdef IS_CGI
      printf("\n
\n"); #endif fclose(f);return; } void printhelp(char*runname) { #ifdef IS_CGI dedicate(); printf("

\n

\n");
#endif
    printf("Usage: %s      for conversion\n",runname);
    printf("    or %s /units [typedef]  for list of unit identificators\n",runname);
    printf("    or %s /units ?          for list of unit typedefs\n\n",runname);
#ifdef IS_CGI
    printf("
"); #endif exit(0); } /* HELP OUTPUT ENDS HERE */ int readinirow(METRICUNIT *met,char *s) { char sn[64]; int st=0,n=0,n1=0,sl=0; int t=0,t1=0; // int st,n,n1,sl; // int t,t1; // st=0;sl=0;n=0; strcat(s," "); memset(met,0,sizeof(METRICUNIT)); if ((s[0]==0) || (s[0]==';')) return(0); while(s[st]==' ') st++; for(t=st;tuname,s); for (t=0;t<14;t++) if ((*m).allowpref[t]) {if ((prefix[t].prefchar==' ')&&(strcmp(s,(*m).ushrt)==0)) return(1);else if ((prefix[t].prefchar==s[0])&&(strcmp(s+1,(*m).ushrt)==0)) {*res*=prefix[t].order;n=strlen(s); if (s[n-1]=='2') *res*=prefix[t].order; if (s[n-1]=='3') {*res*=prefix[t].order;*res*=prefix[t].order;} return(1);}} return(0); } double correctprefix(double prfx,int order) { switch (order) {case 2: return(prfx*prfx); case 3: return(prfx*prfx*prfx); default:return(prfx);} } void convertunit(METRICUNIT *m,double *res,char *s) { int t; double r,r1; char str[20]; int used; int volmod; volmod=1;if (s[strlen(s)-1]=='2') volmod=2;else if (s[strlen(s)-1]=='3') volmod=3; r=0;r1=0;strcpy(str," "); for (t=0;t<14;t++) if ((*m).allowpref[t]) {r1=r; if((prefix[t].orders>=1000)||(volmod>1)) if ((r1==0)||(r1>=prefix[t].orders)) {r=(*res) / correctprefix(prefix[t].order,volmod); str[0]=prefix[t].prefchar;used=t;} } if (str[0]!=' ') {strcat(str,s);strcpy(s,str);*res/=correctprefix(prefix[used].order,volmod);} } void printunit_name(char*s) { char*sp,c=0; sp=strchr(s,'2');if(!sp)sp=strchr(s,'3'); if(sp){c=sp[0];sp[0]=0;} printf("%s",s); #ifdef IS_CGI if(c)printf("%c",c); #else if(c)printf("^%c",c); #endif } void printunit_unit(char*s) { #ifdef IS_CGI if(s[0]==0x10){printf("µ");s[0]=';';}else if(s[0]==0x60){printf("°");s[0]=';';} #else if(s[0]==0x10){s[0]='u';}else if(s[0]==0x60){s[0]='\'';} #endif printunit_name(s); } char*getfracstr(double r,int ismetric) { static char s[32]=""; double fr,in; int t,t1; int steps2=256; int steps3=3^5; int steps5=5^4; int steps7=7^4; int steps; int minstep=-1; int minsteps=-1; double mindiff=2,diff; int primes[]={2,3,5,7,11,13,17,19,23,29,31,37}; int primesteps[]={256,243,625,343,11^3,13^2}; fr=modf(r,&in); if(in>=1000)return NULL; if(fr==0.0)return NULL; // for(t=0;t>=1; // minsteps>>=1; // } // printf(" %12g %4g + %8g %i/%i (%g)\n",r,in,fr,minstep,minsteps,mindiff); if(minstep==0)return NULL; if(mindiff>0.00001)return NULL; if(mindiff>0.000001)if(ismetric)return NULL; if(minsteps==10)return NULL; if(minsteps==100)return NULL; //if(steps>64)return NULL; //printf(" %12g %4g + %8g %i/%i (%g)\n",r,in,fr,minstep,steps,mindiff); if(in>0) snprintf(s,31,"%g %i/%i",in,minstep,minsteps); else snprintf(s,31,"%i/%i",minstep,minsteps); return s; } void printunit(METRICUNIT *m,double r,char *s) { double r1; char sht[20]; char*sfrac; if(!(*m).invert)r1=(r/(*m).conv)+(*m).convadd; else r1=((*m).conv/r)+(*m).convadd; if ((((*m).rangel==0)||((*m).rangelr1))) {strcpy(s,(*m).ushrt); convertunit(m,&r1,s); #ifdef IS_CGI printf(""); printunit_name((*m).uname); printf("    %12g ",r1); printunit_unit(s); printf("\n"); #else sfrac=getfracstr(r1,(*m).metric); if(sfrac==NULL){ printf(" %-20s %12g %s\n",(*m).uname,r1,s); } else { printf(" %-20s %12g %-8s %8s %s\n",(*m).uname,r1,s,sfrac,s); } // printf(" %-20s %12s %s\n",(*m).uname,sfrac,s); #endif } } void dedicate() { #ifdef IS_CGI printf("Dedicated to Tiya\n"); #else printf("Dedicated to Tiya\n"); #endif } void standardizequery(char*s) { if(s[0]=='/')return; for(;;){if(!s[0])return;if(s[0]==' ')return; if(s[0]==',')s[0]='.';else if(s[0]=='"')break; if(s[0]==0x27)break; if(s[0]>='A')break;s++;} memmove(s+1,s,strlen(s)+1); s[0]=' '; } int xstrcompare(char*s,char*s1,char mode,int l) { if(mode=='+') {if(l)return strncasecmp(s,s1,l); return strcasecmp(s,s1);} else {if(l)return strncmp(s,s1,l); return strcmp(s,s1);} } void convertvalue(FILE*f,char*s1) { char s[256],*sp,*sp1; seeksection(f,"[unitmap]"); while(!feof(f)){s[0]=0;fgets(s,256,f);if(s[0]=='[')return; sp=strchr(s,'\n');if(sp)sp[0]=0; if(!s[0])continue;if(s[0]==';')continue; sp=strchr(s,' ');if(!sp)continue; sp[0]=0;sp++;while(sp[0]==' ')sp++; sp1=strchr(s,'*');if(sp1)sp1[0]=0; if(sp1){if(!xstrcompare(s1,s+1,s[0],strlen(s+1))){strcpy(s1,sp);return;}} else{if(!xstrcompare(s1,s+1,s[0],0)) {strcpy(s1,sp);return;}} } } int main(int argc,char*argv[]) { char s[250]; FILE *f; METRICUNIT m; int n,n1,t; double r1,r2; double src,src1; double srcmet; char unit[10]; char unittype[10]; char*paramstr[3]; char params[256]; int paramcnt=3; // char *buffer=NULL; // char rundir[128]; char rundrive[5]; char runname[32]; char runext[16]; // char inifile[200]; #ifdef IS_CGI printf("Content-Type: text/html\r\n\r\n"); logrequest(); #endif // strcpy(params,"1 km"); #ifdef IS_CGI getvarn("QUERY",params,250); #else params[0]=0; if(argc>1)strcat(params,argv[1]); strcat(params," "); if(argc>2)strcat(params,argv[2]); #endif standardizequery(params); paramstr[0]=params;paramstr[1]=params; paramstr[2]=strchr(params,' ');if(!paramstr[2])paramcnt=1; else {paramstr[2][0]=0;paramstr[2]++;} strcpy(runname,"ucalc"); #ifdef IS_CGI printf("\n"); printf("
Unit Calculator v0.99
(C)1997 New Wave Microtechnology

"); if (paramcnt!=3){printhelp(runname);return;} #else if (argc<3){printhelp(runname);return;} #endif if (strcasecmp(paramstr[1],"/UNITS")==0){printhelpunits(paramstr[1],paramstr[2]);return;} //fractional inch char*sp; sp=strchr(paramstr[1],'/'); if(sp){ sp[0]=0;sp++; src=atof(paramstr[1])/atof(sp); } else src=atof(paramstr[1]); // fractional inch 2 sp=strchr(paramstr[2],'/');if(sp){ int v1,v2; sp++; v1=atoi(paramstr[2]); v2=atoi(sp); if(v2!=0){ src=src+((float)v1/(float)v2); strncpy(paramstr[2],argv[3],20); // POTENTIAL BUG HERE! } } // src1=src; f=fopen(INIFILENAME,"r"); if (!f) {printf("INIfile open error on \"%s\"!\n",INIFILENAME);return;} strcpy(unittype,""); // convertvalue(f,paramstr[2]); strncpy(unit,paramstr[2],10); seeksection(f,"[unitdef]"); while (!feof(f)) {s[0]=0; fgets(s,250,f); if (readinirow(&m,s)) if (isunit(&m,unit,&src)) {strcpy(unittype,m.utype); if(!m.invert)srcmet=(src-m.convadd)*m.conv; else srcmet=m.conv/(src-m.convadd); // srcmet=(src-m.convadd)*m.conv; strcpy(rundir,m.utype);strcat(rundir,":");strcat(rundir,m.uname); #ifdef IS_CGI printf("

\n\n"); printf("\n"); #else printf("Input:\n"); printf(" %-20s %12g %s\n\n",rundir,src1,paramstr[2]); #endif // printf(" %-20s %12g %s\n\n",rundir,src1,paramstr[2]); break;} } // if (unittype[0]!=0) { #ifdef IS_CGI printf("\n"); #else printf("Results:\n"); #endif fseek(f,0,SEEK_SET); seeksection(f,"[unitdef]"); while (!feof(f)) {s[0]=0; fgets(s,250,f); if (readinirow(&m,s)) if (strcasecmp(m.utype,unittype)==0) printunit(&m,srcmet,unit); } #ifdef IS_CGI printf("
Input:
    "); printunit_name(rundir); printf("%12g ",src1); printunit_unit(paramstr[2]); printf("
Results:
\n"); #endif } else #ifdef IS_CGI printf("

Unit \"%s\" cannot be recognized

OR

'Improper use of prefix'.

\n",unit); #else printf("Unit \"%s\" cannot be recognized OR 'Improper use of prefix'.\n",unit); #endif fclose(f); printf("\n"); #ifdef IS_CGI printf("\n"); #endif return 0; }