Newsgroups: comp.sys.apple2.programmer
Path: news.uiowa.edu!hobbes.physics.uiowa.edu!newsrelay.iastate.edu!vixen.cso.uiuc.edu!howland.reston.ans.net!agate!ames!waikato!comp.vuw.ac.nz!actrix.gen.nz!dempson
From: dempson@atlantis.actrix.gen.nz (David Empson)
Subject: Re: using C with pascal
Message-ID: <DCw511.9Hr@actrix.gen.nz>
Sender: news@actrix.gen.nz (News Administrator)
Organization: Actrix - Internet Services
Date: Sun, 6 Aug 1995 13:19:47 GMT
References: <4020i5$4no@bbs.ausom.net.au>
X-Nntp-Posting-Host: atlantis.actrix.gen.nz
Lines: 276

> Can someone help me I am tring to uses the functions build into ORCA/C
> to calculate the day of the week and day in year for a pascal program.

OK.

> What am I doing wrong?

The following is your program, with my comments and suggested
corrections. I have NOT used the normal "quoting" notation here.

************************************************************
pascal program

program test2 (input,output);

type

    ptr_tm  =   ^tm;

    tm      =   record
        second :    integer;
        minute :    integer;
        hour :      integer;
        day :       integer;
        month :     integer;
        year :      integer;
        Wday :      integer;
        dayofYear : integer;
        isdaysave : integer;
    end;


var
    my_time :   longint;
    MY_Int  :   integer;
    timerec :   tm;
    ptr_time :  ptr_tm;

function GetTime : longint; extern;

(* You had: function GetTime ( myin : integer ) : longint; extern;
   I see no reason for the dummy integer parameter. *)

function FixDayWeek ( mytime : ptr_tm ) : ptr_tm; extern;

(* You had: function FixDayWeek ( myin : univ longint ) : longint;
            extern;
   You may as well use the correct types. *)

procedure PrintTime ( My_Time : ptr_tm);

begin
    writeln ( 'Pointer  :',ord4(my_time));
(* You spelled "Pointer" wrong above.  In the following output, you are
   going to get strange values for the month, which is stored as 0-11
   in the original struct tm: add one for the normal notation.
   Similarly, the year is 0-based at 1900, so add 1900 to get the year
   in normal notation. *)

    with my_time^ do begin

        writeln ( 'date : ',day:2,'/',month:2,'/',year:4);
        writeln ('Time : ',hour:2,':',minute:2,':',second:2);
        writeln ( 'day of week : ',wday:2,' Day of Year : ',dayofyear:2);
    end;
end;

begin

    My_time := 0;
    MY_int := 0  ;   (* This isn't needed *)
    writeln ('This is my Time now ',My_time);

    MY_Time := GetTime (* (MY_Int) *);
    writeln ('This is my Time after calling time ',My_time);

    with timerec do begin
        day := 2;
        month := 4;     (* This will be May.  Use 3 for April. *)
        year := 95;     (* Your version had 1995 *)
        second := 2;
        minute :=33;
        hour :=12;
        Wday :=0;
        dayofyear :=0;
        (* You should also add the following line: *)
        isdaysave := 0;
    end;
    writeln (' Time before Call');
    PrintTime ( @timerec );
    ptr_time := @timerec;
    ptr_time := FixDayWeek ( ptr_time ); (* no typecast now *)
    PrintTime ( ptr_time);
end.

*********************************************************************

the C functions

/********************/

#pragma keep "timec"
#pragma noroot
#pragma lint -1

#include "time.h"
#include "intmath.h"
#include "stdio.h"

pascal LongWord GetTime (void)   /* was (Word MY_in) */
{
    LongWord gstime;
    gstime = time(NULL);
    return gstime;
    /* This could be simplified to one line: return time(NULL); */
}

pascal  struct tm * FixDayWeek ( struct tm *my_ptr )
{
    struct tm time_rec;
    struct tm *ptr_tm;
    time_t mytime;
    /* unsigned long   ptr; */   /* Not used */
    int    p;                    /* was char - getchar() returns int */

    /* ptr_tm = my_ptr; */       /* Not necessary */
    printf("%lx",my_ptr);        /* was "%x" */
    /* printf("%x",*my_ptr); */  /* This line is bad - see below */
    p = getchar();
    mytime = mktime(my_ptr /* was ptr_tm */);
    printf("%lx",mytime);        /* was "%x" */
    p = getchar();
    ptr_tm = localtime(&mytime);
    printf("%lx",ptr_tm);        /* was "%x" */
    p = getchar() ;

    return  ptr_tm;
}

********************

Regarding the printf() I commented out: you were passing the contents
of the structure and trying to print the first word as a hex value.
The rest of it would have been left on the stack, which might have
caused a crash, depending on whether you were optimizing the code.

Similarly, your other printf() calls were passing larger values than
they were printing.


In general, I can't see anything fundamentally wrong with what you are
doing.  The localtime() call is not strictly necessary, as mktime()
will recalculate tm_wday and tm_yday in your input structure.


Here is a much more versatile way of calculating the day of week, all
done in Pascal, though it does use the IIgs toolbox.  System 5.0.3 or
later is required. The main point of this program is to demonstrate
the use of the ConvSeconds toolbox call, which does everything you
need.

program ConvSecondsExample(output);

uses Common, MscToolSet;

const
  (* Conversion verb (first parameter) for ConvSeconds *)
  ConvSecsToTimeRec = 0;    (* Convert to time record *)
  ConvTimeRecToSecs = 1;    (* Convert from time record *) 
  ConvSecsToAscii = 2;      (* Convert to ASCII-formatted time *)
  ConvSecsToProDOS = 4;     (* Convert to ProDOS packed time *)
  ConvProDOSToSecs = 5;     (* Convert from ProDOS packed time *)
  ConvGetTime = 6;          (* Get current time in seconds *)
  ConvSetTime = 7;          (* Set current time in seconds *)
  ConvProDOSToTimeRec = 8;  (* Convert ProDOS to TimeRec in place *)
  ConvTimeRecToProDOS = 9;  (* Convert TimeRec to ProDOS in place *)
  ConvSecsToHyperCard = 10; (* Convert to HyperCard time record *)
  ConvHyperCardToSecs = 11; (* Convert from HyperCard time record *)

type
  TimeRec = record
    second : byte;   (* 0 to 59 *)
    minute: byte;    (* 0 to 59 *)
    hour : byte;     (* 0 to 23 *)
    year : byte;     (* year minus 1900 *)
    day : byte;      (* 0 to 30: add 1 for normal day *)
    month : byte;    (* 0 to 11: add 1 for normal month *)
    extra : byte;    (* unused - only required for positioning *)
    weekDay : byte;  (* 1 to 7, with 1 = Sunday *)
  end;

var
  myTimeRec : TimeRec;
  mySeconds, dummy : longint;

Begin
  with myTimeRec do
  begin
    day := 1;   (* day is zero-based: add 1 for normal notation *)
    month := 4; (* month is zero-based: add 1 for normal notation *)
    year := 95;
    second := 2;
    minute := 33;
    hour := 12;
  end;
  (* ConvSeconds expects three parameters:

     First parameter is the conversion verb (see constants above).

     Second parameter is the "seconds" value, when converting from
     seconds to another format, or 0 if not used.

     Third parameter is a pointer to the input or output data structure
     for most operations.

     The return value is the "seconds" value when converting to seconds
     from another format, or undefined otherwise.

     The "seconds" type is a long integer which contains the number of
     seconds since 1st January 1904.

  *)

  (* We have a record in standard TimeRec format, so convert it to
     seconds. *)

  myseconds := ConvSeconds(ConvTimeRecToSecs, 0, @myTimeRec);

  (* Now convert the seconds back to a TimeRec, which will give us the
     day of week.  The return value must be ignored. *)

  dummy := ConvSeconds(ConvSecsToTimeRec, myseconds, @myTimeRec);

  (* Add code in here to do the necessary extra steps, e.g. *)
  writeln('The day of the week was ', myTimeRec.weekDay);
end.


If you want to get the current time (in seconds), use:

   seconds := ConvSeconds(ConvGetTime, 0, NIL);

The "HyperCard" format mentioned in the constants is the same data
structure as TimeRec, except that "day" and "month" start at one
instead of zero.

You are unlikely to need ProDOS format.

ASCII format is rather messy. It produces a packed array of 20
characters containing the time in the order specified by the Control
Panel. There is no end terminator, and the characters are in high
ASCII, so they should be converted to low ASCII before use. The buffer
needs to be at least 40 bytes long, even though only 20 bytes are used.

Here is an example of how it can be used:

type
  Str20 = packed array[0..20] of char;

Procedure TimeString(seconds: longint; var timeStr: Str20);
const
  ConvSecsToAscii = 2;      (* Convert to ASCII-formatted time *)
var
  timebuf : packed array[1..40] of byte;
  i : integer;
  dummy : longint;
begin
  dummy := ConvSeconds(ConvSecsToASCII, seconds, @timebuf);
  for i := 1 to 20 do
    timeStr[i] := chr(timebuf[i] - 128);
  timeStr[0] := 20;         (* Set the string length *)
end; (*TimeString*)
-- 
David Empson
dempson@actrix.gen.nz
Snail mail: P.O. Box 27-103, Wellington, New Zealand
