home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c163 / 3.ddi / SCRE_SOU.EXE / C4_F.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-29  |  12.1 KB  |  547 lines

  1.  
  2. /*  c4_f.c   Conversion Routines
  3.        (c)Copyright Sequiter Software Inc., 1987-1990.  All rights reserved.
  4. */
  5.  
  6. #include "d4all.h"
  7. #include "u4error.h"
  8. #include "p4misc.h"
  9.  
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <stdlib.h>
  13.  
  14. #define  JULIAN_ADJUSTMENT    1721425L
  15.  
  16.  
  17. static    char  buffer[130] ;
  18. #ifdef LANGUAGE
  19. static    char  month[][10]= {"         ",
  20.                 "Januar   ",
  21.                 "Februar  ",
  22.                 "März     ",
  23.                 "April    ",
  24.                 "Mai      ",
  25.                 "Juni     ",
  26.                 "Juli     ",
  27.                 "August   ",
  28.                 "September",
  29.                 "Oktober  ",
  30.                 "November ",
  31.                 "Dezember "
  32.               } ;
  33.  
  34. #else
  35. static    char  month[][10]= {"         ",
  36.                 "January  ",
  37.                 "February ",
  38.                 "March    ",
  39.                 "April    ",
  40.                 "May      ",
  41.                 "June     ",
  42.                 "July     ",
  43.                 "August   ",
  44.                 "September",
  45.                 "October  ",
  46.                 "November ",
  47.                 "December "
  48.               } ;
  49. #endif
  50.  
  51. /*  c4dt_format
  52.  
  53.     Formats a date from   CCYYMMDD  (Century, Year, Month, Day)
  54.     format to any date format.
  55.  
  56.     The length of 'picture' must be 32 or less.
  57.  
  58.     If there are more than 2 'M' characters in the picture, the
  59.     month will be in character form.
  60. */
  61.  
  62. char  *c4dt_format( char *dbf_date, char *picture )
  63. {
  64.    char *ptr, *ptr_end ;
  65.    int     rest, len, m_num    ;
  66.  
  67.    memset( buffer, (int) ' ', (size_t) sizeof(buffer) ) ;
  68.  
  69.    c4encode( buffer, dbf_date, picture, "CCYYMMDD") ;
  70.  
  71.    ptr_end  =  strchr( picture, 'M' ) ;
  72.    if ( ptr_end  !=  (char *) 0 )
  73.    {
  74.       ptr =  buffer+  (int) (ptr_end-picture) ;
  75.       len     =  0 ;
  76.       while ( *(ptr_end++) == 'M' )  len++ ;
  77.  
  78.       if ( len > 2)
  79.       {
  80.      /* Convert from a numeric form to character format for month */
  81.  
  82.      m_num =  c4atoi( dbf_date+4, 2) ;
  83.      if ( m_num < 0)  m_num =  1 ;
  84.      if ( m_num > 12) m_num = 12 ;
  85.  
  86.      rest =  len - 9 ;
  87.      if (len > 9) len = 9 ;
  88.  
  89.      memcpy( ptr, month[m_num], (size_t) len ) ;
  90.      if (rest > 0)    memset( ptr+len, (int) ' ', (size_t) rest ) ;
  91.       }
  92.    }
  93.    return( buffer );
  94. }
  95.  
  96.  
  97. /* Converts from formatted Date Data into '.DBF' (CCYYMMDD) format */
  98.  
  99. char  *c4dt_unformat( char *date_data, char *picture )
  100. {
  101.    char  *month_start, month_data[10] ;
  102.    int     year_count, month_count, day_count, century_count, i, len ;
  103.  
  104.    day_count    =  5 ;
  105.    month_count    =  3 ;
  106.    year_count    =  1 ;
  107.    century_count= -1 ;
  108.  
  109.    memset( buffer, (int) ' ', (size_t) 8 ) ;
  110.    buffer[8] =    '\000' ;
  111.  
  112.    for ( i=0; picture[i] != '\000'; i++ )
  113.    {
  114.       switch( picture[i] )
  115.       {
  116.      case 'D':
  117.         if ( ++day_count >= 8) break ;
  118.         buffer[day_count] =  date_data[i] ;
  119.         break ;
  120.  
  121.      case 'M':
  122.         if ( ++month_count >=6) break ;
  123.         buffer[month_count] =  date_data[i] ;
  124.         break ;
  125.  
  126.      case 'Y':
  127.         if ( ++year_count >= 4) break ;
  128.         buffer[year_count] =  date_data[i] ;
  129.         break ;
  130.  
  131.      case 'C':
  132.         if ( ++century_count >= 2) break ;
  133.         buffer[century_count] =  date_data[i] ;
  134.         break ;
  135.       }
  136.    }
  137.  
  138.    if ( strcmp( buffer, "        " ) == 0 )  return( buffer ) ;
  139.  
  140.    if ( century_count ==  -1 )    memcpy( buffer,   "19", (size_t) 2 ) ;
  141.    if ( year_count    ==   1 )    memcpy( buffer+2, "01", (size_t) 2 ) ;
  142.    if ( month_count   ==   3 )    memcpy( buffer+4, "01", (size_t) 2 ) ;
  143.    if ( day_count     ==   5 )    memcpy( buffer+6, "01", (size_t) 2 ) ;
  144.  
  145.    if ( month_count >= 6 )
  146.    {
  147.       /* Convert the Month from Character Form to Date Format */
  148.       month_start =  strchr( picture, 'M' ) ;
  149.  
  150.       len =  month_count - 3 ;    /* Number of 'M' characters in picture */
  151.  
  152.       memcpy( buffer+4, "  ", (size_t) 2 ) ;
  153.  
  154.       if ( len > 3 ) len = 3 ;
  155.       memcpy( month_data, date_data+ (int) (month_start-picture), (size_t) len) ;
  156.       while ( len > 0 )
  157.      if ( month_data[len-1] == ' ' )
  158.         len-- ;
  159.      else
  160.         break ;
  161.  
  162.       month_data[len] =  '\000' ;
  163.  
  164.       u4lower( month_data ) ;
  165.       month_data[0] =  (char) u4toupper( (int) month_data[0] ) ;
  166.  
  167.       if ( len > 0 )
  168.      for( i=1; i<= 12; i++ )
  169.      {
  170.         if ( memcmp( month[i], month_data, (size_t) len) == 0 )
  171.         {
  172.            c4ltoa( (long) i, buffer+4, 2 ) ;  /* Found Month Match */
  173.            break ;
  174.         }
  175.      }
  176.    }
  177.  
  178.    for ( i=0; i< 8; i++ )
  179.       if ( buffer[i] == ' ' )  buffer[i] =  '0' ;
  180.  
  181.    return ( buffer) ;
  182. }
  183.  
  184. /*  c4ltoa
  185.  
  186.     Converts a RECNUM to a string.  Fill with '0's rather than blanks if
  187.     'num' is less than zero.
  188. */
  189.  
  190. char *c4ltoa( long l_val, char *ptr, int num)
  191. {
  192.    int     n, num_pos ;
  193.    long  i_long ;
  194.  
  195.    i_long =  (l_val>0) ? l_val : -l_val ;
  196.    num_pos =  n =  (num > 0) ? num : -num ;
  197.  
  198.    while (n-- > 0)
  199.    {
  200.       ptr[n] = (char) ('0'+ i_long%10) ;
  201.       i_long = i_long/10 ;
  202.    }
  203.  
  204.    if ( i_long > 0 )
  205.    {
  206.      memset( ptr, (int) '*', (size_t) num_pos ) ;
  207.      return ptr ;
  208.    }
  209.  
  210.    num--;
  211.    for (n=0; n<num; n++)
  212.       if (ptr[n]=='0')
  213.      ptr[n]= ' ';
  214.       else
  215.      break ;
  216.  
  217.    if (l_val < 0)
  218.    {
  219.       if ( ptr[0] != ' ' )
  220.       {
  221.      memset( ptr, (int) '*', (size_t) num_pos ) ;
  222.      return ptr ;
  223.       }
  224.       for (n=num; n>=0; n--)
  225.      if (ptr[n]==' ')
  226.      {
  227.         ptr[n]= '-' ;
  228.         break ;
  229.      }
  230.    }
  231.  
  232.    return(ptr) ;
  233. }
  234.  
  235. /* c4dtoa( doub_val, len, dec)
  236.  
  237.    - formats a double to a string
  238.    - if there is an overflow, '*' are returned
  239.  
  240.    Return
  241.  
  242.       Pointer to the Formatted String
  243. */
  244.  
  245. char * c4dtoa( double doub_val, int len, int dec)
  246. {
  247.    int     dec_val, sign_val ;
  248.    int     pre_len, post_len, sign_pos ; /* pre and post decimal point lengths */
  249.    char *result, *out_string ;
  250.  
  251.    if ( len < 0 )    len = -len  ;
  252.    if ( len > 128 )  len =  128 ;
  253.  
  254.    memset( buffer, (int) '0', (size_t) len) ;
  255.    out_string =  buffer ;
  256.  
  257.    if (dec > 0)
  258.    {
  259.       post_len =  dec ;
  260.       if (post_len > 15)     post_len =  15 ;
  261.       if (post_len > len-1)  post_len =  len-1 ;
  262.       pre_len  =  len -post_len -1 ;
  263.  
  264.       out_string[ pre_len] = '.' ;
  265.    }
  266.    else
  267.    {
  268.       pre_len  =  len ;
  269.       post_len = 0 ;
  270.    }
  271.  
  272.    result =  fcvt( doub_val, post_len, &dec_val, &sign_val) ;
  273.  
  274.    if (dec_val > 0)
  275.       sign_pos =   pre_len-dec_val -1 ;
  276.    else
  277.    {
  278.       sign_pos =   pre_len - 2 ;
  279.       if ( pre_len == 1) sign_pos = 0 ;
  280.    }
  281.  
  282.    if ( dec_val > pre_len ||  pre_len<0  ||  sign_pos< 0 && sign_val)
  283.    {
  284.       /* overflow */
  285.       memset( out_string, (int) '*', (size_t) len) ;
  286.       return( buffer) ;
  287.    }
  288.  
  289.    if (dec_val > 0)
  290.    {
  291.       memset( out_string, (int) ' ', (size_t) pre_len- dec_val) ;
  292.       memmove( out_string+ pre_len- dec_val, result, (size_t) dec_val) ;
  293.    }
  294.    else
  295.    {
  296.       if (pre_len> 0)  memset( out_string, (int) ' ', (size_t) (pre_len-1)) ;
  297.    }
  298.    if ( sign_val)  out_string[sign_pos] = '-' ;
  299.  
  300.  
  301.    out_string += pre_len+1 ;
  302.    if (dec_val >= 0)
  303.    {
  304.       result+= dec_val ;
  305.    }
  306.    else
  307.    {
  308.       out_string    -= dec_val ;
  309.       post_len += dec_val ;
  310.    }
  311.  
  312.    if ( post_len > (int) strlen(result) )
  313.       post_len =  (int) strlen( result) ;
  314.  
  315.    /*  - out_string   points to where the digits go to
  316.        - result       points to where the digits are to be copied from
  317.        - post_len     is the number to be copied
  318.    */
  319.  
  320.    if (post_len > 0)   memmove( out_string, result, (size_t) post_len) ;
  321.  
  322.    buffer[len] =  '\000' ;
  323.  
  324.    return( buffer ) ;
  325. }
  326.  
  327.  
  328. extern double floor( double ) ;
  329.  
  330. /*  static c4julian
  331.  
  332.        Returns an (int) day of the year starting from 1.
  333.        Ex.    Jan 1, returns  1
  334.  
  335.        Returns    -1  if it is an illegal date.
  336.  
  337. */
  338.  
  339. static int  month_tot[]=
  340.     { 0, 0,  31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 } ;
  341.      /* Jan Feb Mar  Apr  May  Jun    Jul  Aug  Sep  Oct  Nov  Dec
  342.          31  28  31   30   31   30     31   31   30    31   30   31
  343.      */
  344.  
  345. int c4julian( int year, int month, int day )
  346. {
  347.    int    is_leap, month_days ;
  348.  
  349.    is_leap =   ( year%4 == 0 && year%100 != 0 || year%400 == 0 ) ?  1 : 0 ;
  350.  
  351.    month_days =  month_tot[ month+1 ] -  month_tot[ month] ;
  352.    if ( month == 2 )  month_days += is_leap ;
  353.  
  354.    if ( year  < 0  ||
  355.     month < 1  ||  month > 12  ||
  356.     day   < 1  ||  day   > month_days )
  357.     return( -1 ) ;    /* Illegal Date */
  358.  
  359.    if ( month <= 2 )  is_leap = 0 ;
  360.  
  361.    return(  month_tot[month] + day + is_leap ) ;
  362. }
  363.  
  364. /*   c4ytoj -  Calculates the number of days to the year */
  365. static long  c4ytoj( int ) ;
  366.  
  367. static long  c4ytoj( int yr )
  368. {
  369.    /*
  370.        This calculation takes into account the fact that
  371.       1)  Years divisible by 400 are always leap years.
  372.       2)  Years divisible by 100 but not 400 are not leap years.
  373.       3)  Otherwise, years divisible by four are leap years.
  374.  
  375.        Since we do not want to consider the current year, we will
  376.        subtract the year by 1 before doing the calculation.
  377.    */
  378.  
  379.    yr-- ;
  380.    return( yr*365L +  yr/4L - yr/100L + yr/400L ) ;
  381. }
  382.  
  383.  
  384. /*   c4dt_julian
  385.  
  386.      Converts from database to index file date format.
  387.  
  388.      Can be used for checking the validity of a date.
  389.  
  390.      Returns
  391.     0 -  Valid Date
  392.        -1 -  Illegal Date
  393.        -2 -  NULL Date (dbf_date is all blank; converts to 1.0E100)
  394. */
  395.  
  396. int  c4dt_julian( char *dbf_date, double *index_date)
  397. {
  398.    int     year, month, day, day_year ;
  399.    long  total ;
  400.  
  401.    /* A dBASE III index file date is stored as a julian day.  That is the
  402.       number of days since the date  Jan 1, 4713 BC
  403.       Ex.  Jan 1, 1981 is  2444606
  404.    */
  405.  
  406.    year   =  c4atoi( dbf_date,     4) ;
  407.    if ( year == 0)
  408.    {
  409.       if ( memcmp( dbf_date, "        ", 8 ) == 0)
  410.       {
  411.     *index_date =  1.0E100 ;
  412.      return( -2) ;
  413.       }
  414.    }
  415.  
  416.    month  =  c4atoi( dbf_date+4, 2) ;
  417.    day      =  c4atoi( dbf_date+6, 2) ;
  418.  
  419.    day_year    =  c4julian( year, month, day) ;
  420.    if (day_year < 1)  return( -1) ;  /* Illegal Date */
  421.  
  422.    total =  c4ytoj(year) ;
  423.    total+=  day_year ;
  424.    total+=  JULIAN_ADJUSTMENT ;
  425.   *index_date  = (double) total ;
  426.  
  427.    return( 0) ;
  428. }
  429.  
  430.  
  431. /*  c4mon_dy
  432.  
  433.        Given the year and the day of the year, returns the
  434.     month and day of month.
  435. */
  436. static  int    c4mon_dy( int, int, int *, int *) ;
  437.  
  438. static int  c4mon_dy( int year, int days,  int *month_ptr,  int *day_ptr )
  439. {
  440.    int is_leap, i ;
  441.  
  442.    is_leap =  ( year%4 == 0 && year%100 != 0 || year%400 == 0 ) ?  1 : 0 ;
  443.    if ( days <= 59 )  is_leap = 0 ;
  444.  
  445.    for( i = 2; i <= 13; i++)
  446.    {
  447.       if ( days <=  month_tot[i] + is_leap )
  448.       {
  449.      *month_ptr =  --i ;
  450.      if ( i <= 2) is_leap = 0 ;
  451.  
  452.      *day_ptr   =  days - month_tot[ i] - is_leap ;
  453.      return( 0) ;
  454.       }
  455.    }
  456.    *day_ptr   =  0 ;
  457.    *month_ptr =  0 ;
  458.  
  459.    return( -1 ) ;
  460. }
  461.  
  462.  
  463. /*   c4dt_str
  464.  
  465.      Converts from the index file date format to the dbf file date format.
  466. */
  467.  
  468. void  c4dt_str( char *dbf_date, double *index_date)
  469. {
  470.    int     year, month, day, n_days, max_days ;
  471.    long  tot_days ;
  472.  
  473.    /* A dBASE III index file date is stored as a julian day.  That is the
  474.       number of days since the date  Jan 1, 4713 BC
  475.       Ex.  Jan 1, 1981 is  2444606
  476.    */
  477.  
  478.    if ( *index_date == 1.0E100 )
  479.    {
  480.       memcpy( dbf_date, "        ", 8 ) ;
  481.       return ;
  482.    }
  483.  
  484.    tot_days    =  (long) (*index_date) - JULIAN_ADJUSTMENT ;
  485.  
  486.    year        =  (int) ((double)tot_days/365.2425) + 1 ;
  487.    n_days      =  (int) (tot_days -  c4ytoj(year)) ;
  488.    if ( n_days <= 0 )
  489.    {
  490.       year-- ;
  491.       n_days   =  (int) (tot_days - c4ytoj(year)) ;
  492.    }
  493.    if (year%4 == 0 && year%100 != 0 || year%400 == 0)
  494.       max_days =  366 ;
  495.    else
  496.       max_days =  365 ;
  497.  
  498.    if ( n_days > max_days )
  499.    {
  500.       year++ ;
  501.       n_days -= max_days ;
  502.    }
  503.  
  504.    if ( c4mon_dy( year, n_days, &month, &day ) < 0 )
  505.     u4error( E_INTERNAL,"C3DT_DBF", (char *) 0 ) ;
  506.  
  507.    c4ltoa( (long) year,  dbf_date,   -4 ) ;
  508.    c4ltoa( (long) month, dbf_date+4, -2 ) ;
  509.    c4ltoa( (long) day,     dbf_date+6, -2 ) ;
  510. }
  511.  
  512. #ifdef CLIPPER
  513. /* Numeric Key Database Output is Converted to Numeric Key Index File format */
  514. c4clip( char *ptr, int len)
  515. {
  516.    int     i, negative ;
  517.    char *p ;
  518.  
  519.    for ( i= negative= 0, p= ptr; i< len; i++, p++ )
  520.    {
  521.       if ( *p == ' ' )
  522.       {
  523.      *p =  '0' ;
  524.       }
  525.       else
  526.       {
  527.      if ( *p == '-' )
  528.      {
  529.         *p =  '0' ;
  530.         negative =    1 ;
  531.      }
  532.      else
  533.         break ;
  534.       }
  535.    }
  536.  
  537.    if ( negative )
  538.    {
  539.       for ( i= 0, p= ptr; i< len; i++, p++ )
  540.      *p =  (char) 0x5c - *p ;
  541.    }
  542.  
  543.    return 0 ;
  544. }
  545. #endif
  546.  
  547.