/*
 * setdate.c
 *
 * Generate AOF file containing date strings
 *
 *  1994-1998 Straylight
 */

/*----- Licensing note ----------------------------------------------------*
 *
 * This file is part of Straylight's core utilities (coreutils).
 *
 * Coreutils is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * Coreutils is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with coreutils.  If not, write to the Free Software Foundation,
 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/*----- Header files ------------------------------------------------------*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#include "swis.h"
#include "kernel.h"

#include "aof/aof.h"
#include "aof/chunk.h"

#include "_time.h"

/*----- Main code ---------------------------------------------------------*/

static aof_file setdate_aof;

static int cistrcmp(const char *s1,const char *s2)
{
  char c1;
  char c2;
  while (*s1 || *s2)
  {
    c1=tolower(*(s1++));
    c2=tolower(*(s2++));
    if (c1!=c2)
      return (c1-c2);
  }
  return (0);
}

void aof_error(void)
{
  fprintf(stderr,"setdate: not enough memory.\n");
  exit(1);
}

static void setdate_addSymbol(char *ident,char *format)
{
  _kernel_swi_regs r;
  int osword[20];
  char string[256];
  char time[256];
  char *p,*q,c;

  /* --- Get the current date --- */

  osword[0]=3;
  _kernel_osword(14,osword);
  r.r[0]=(int)osword;
  r.r[1]=(int)time;
  r.r[2]=256;
  r.r[3]=(int)format;
  if (_kernel_swi(OS_ConvertDateAndTime,&r,&r)!=0)
  {
    fprintf(stderr,"setdate: invalid date format.\n");
    exit(1);
  }

  /* --- Translate our own magic control characters in the string --- */

  p=time;
  q=string;
  while (*p)
  {
    switch (c=*p++)
    {
      case '\\':
        switch (c=*p++)
        {
          case 't':
            if (q-string<8)
              *q++=9;
            *q++=9;
            break;
          case '\\':
            *q++='\\';
            break;
        }
        break;
      default:
        *q++=c;
        break;
    }
  }
  *q=0;

  /* --- Add the string to the AREA and give it a symbol --- */

  aof_addsym(ident,
             aof_string(string,setdate_aof.area),
             0,
             4,
             &setdate_aof);
}

int main(int argc,char *argv[])
{
  int o;
  int i;
  char *p;
  char *format;
  FILE *fp;
  char *pname;

  aof_chunkinfo obj_area={0};
  aof_chunkinfo obj_symt={0};
  aof_chunkinfo obj_strt={0};
  aof_chunkinfo reloc={0};
  aof_chunkinfo obj_head={0};
  aof_chunkinfo obj_idfn={0};

  pname=strrchr(argv[0],'.');
  if (!pname)
    pname=argv[0];
  else
    pname++;

  if (argc==1)
  {
    fprintf(stderr,
            "Usage: %s <outfile> <identifier>[=<dateformat>]...\n",
            pname);
    exit(0);
  }
  else if (!cistrcmp(argv[1],"-help"))
  {
    fprintf(stderr,

"%s version 1.00 [%s]\n"
"\n"
"   1994 Straylight\n"
"\n"
"Syntax: %s <outfile> <identifier>[=<dateformat>]...\n"
"\n"
"dateformat contains literal characters and format specifiers.  Format\n"
"specifiers consist of a '%%' sign, an optional 'z' (indicating\n"
"suppression of leading zero) and a two character format string, as\n"
"follows:\n"
"\n"
"String  Value\n"
"\n"
"  cs    centiseconds\n"
"  se    seconds\n"
"  mi    minutes\n"
"  12    12-hour style hours\n"
"  24    14-hour style hours\n"
"am/pm   'am' or 'pm' as appropriate\n"
"  we    full weekday name\n"
"  w3    abbreviated weekday name\n"
"  wn    weekday number\n"
"  dy    day of the month\n"
"  st    suffix for day (e.g. 'st', 'nd', 'th' etc.)\n"
"  mo    full month name\n"
"  m3    abbreviated month name\n"
"  mn    month number\n"
"  ce    century number\n"
"  yr    year number within century\n"
"  wk    number of week in the year\n"
"  dn    number of day in the year\n"
"  tz    current time zone name\n"
"  %%     insert a literal '%%' sign\n"
"\n"
"If no dateformat is specifed, a default of '%%zdy %%mo %%ce%%yr' is\n"
"used.\n",

            pname,
            _time,
            pname);
    exit(0);
  }

  if (fp=fopen(argv[1],"wb"),!fp)
  {
    fprintf(stderr,"setdate: couldn't open output file.\n");
    exit(1);
  }

  setdate_aof.area=&obj_area;
  setdate_aof.symt=&obj_symt;
  setdate_aof.strt=&obj_strt;
  setdate_aof.reloc=&reloc;

  /* --- Set up module identification --- */

  aof_string("Straylight setdate utility 1.00",
             &obj_idfn);
  aof_align(obj_idfn);

  /* --- Add in the AREA name --- */

  aof_int(0,&obj_strt);
  aof_string("SetDate$$Data",&obj_strt);

  /* --- Create the date information in the AREA section --- */

  for (i=2;i<argc;i++)
  {
    format="%zDY %MO %CE%YR";
    for (p=argv[i];*p;p++)
    {
      if (*p=='=')
      {
        *p=0;
        format=p+1;
      }
    }
    setdate_addSymbol(argv[i],format);
  }
  aof_align(obj_area);

  /* --- Build AOF header information --- */

  aof_int((int)aof_RELOC,&obj_head);
  aof_int(200,&obj_head);
  aof_int(1,&obj_head);
  aof_int(obj_symt.next/sizeof(aof_symbol),&obj_head);
  aof_int(0,&obj_head);
  aof_int(0,&obj_head);

  aof_int(4,&obj_head);
  aof_int(0x00002202,&obj_head);
  aof_int(obj_area.next,&obj_head);
  aof_int(reloc.next/8,&obj_head);
  aof_int(0,&obj_head);

  /* --- Add relocation stuff to AREA chunk --- */

  aof_addBlock(reloc.p,reloc.next,&obj_area);

  /* --- Complete string table by adding length word --- */

  aof_fill(obj_strt.next,0,&obj_strt);
  aof_align(obj_strt);

  /* --- Write completed AOF file out to disk */

  {
    char _buf[sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry)];
    chunk_header *h=(chunk_header *)&_buf;

    h->hdr.id=chunk_MAGIC;
    h->hdr.maxChunks=h->hdr.numChunks=5;

    memcpy(h->table[0].chunkName,"OBJ_IDFN",8);
    memcpy(h->table[1].chunkName,"OBJ_HEAD",8);
    memcpy(h->table[2].chunkName,"OBJ_AREA",8);
    memcpy(h->table[3].chunkName,"OBJ_SYMT",8);
    memcpy(h->table[4].chunkName,"OBJ_STRT",8);

    o=sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry);

    h->table[0].offset=o;
    h->table[0].size=obj_idfn.next;
    o+=obj_idfn.next;

    h->table[1].offset=o;
    h->table[1].size=obj_head.next;
    o+=obj_head.next;

    h->table[2].offset=o;
    h->table[2].size=obj_area.next;
    o+=obj_area.next;

    h->table[3].offset=o;
    h->table[3].size=obj_symt.next;
    o+=obj_symt.next;

    h->table[4].offset=o;
    h->table[4].size=obj_strt.next;
    o+=obj_strt.next;

    fwrite(h,sizeof(chunk_fixedHeader)+5*sizeof(chunk_tableEntry),1,fp);
    fwrite(obj_idfn.p,obj_idfn.next,1,fp);
    fwrite(obj_head.p,obj_head.next,1,fp);
    fwrite(obj_area.p,obj_area.next,1,fp);
    fwrite(obj_symt.p,obj_symt.next,1,fp);
    fwrite(obj_strt.p,obj_strt.next,1,fp);
    fclose(fp);

    free(obj_idfn.p);
    free(obj_area.p);
    free(obj_strt.p);
    free(obj_head.p);
    free(obj_symt.p);
  }
}
