% $Id: tex4ht-htcmd.tex 748 2020-06-29 22:18:30Z karl $
%       tex tex4ht-htcmd
% or ht tex tex4ht-htcmd
%
% htcmd is apparently not used for anything, but this .tex file is
% preserved for history.
%
% htcmd OPTFLAG CMDLINE  passed CMDLINE to system(), translating each
% forward slash into a single or double backslash for OPTFLAG set to
% -slash or -dslash respectively.
%
% Copyright 2009-2020 TeX Users Group
% Copyright 1996-2009 Eitan M. Gurari
% Released under LPPL 1.3c+.
% See tex4ht-cpright.tex for license text.

\input common
\input tex4ht.sty

\Preamble{xhtml,th4,sections+,xhtml}\EndPreamble

  \input ProTex.sty
  \AlProTex{c,<<<>>>,`,title,list,_^}

%\input tex4ht-cpright.tex (see below)

\Comment{
}{}
\def\CodeId#1#2{}


\def\UnderLine#1{\ifHtml
  \HCode{<strong>}#1\HCode{</strong>}\else\underbar{#1}\fi}
\let\CModifyShowCode=\ModifyShowCode
\let\CModifyOutputCode=\ModifyOutputCode
\def\ModifyShowCode{\def\[##1({##1\UnderLine{(}}\def
                       \;{\UnderLine{;}}\CModifyShowCode}
  \catcode`\^=7  \catcode`\@=6  \catcode`\#=12 \catcode`\^^M=13\relax%
\def\ModifyOutputCode{%
\def\;{ SEP }%
\def\[@@1(@@2)@@3;{@@1
#ifdef ANSI
#define SEP  ,
(@@3)
#undef  SEP
#else
#define SEP  ;
(@@2)@@3;
#undef  SEP
#endif
}%
\CModifyOutputCode}%
  \catcode`\^^M=5 \catcode`\@=12 \catcode`\#=6 \catcode`\^=13


\let\'=\Verb
\def\`{\expandafter\expandafter\expandafter\qts\Verb}
\def\qts#1{`#1\aftergroup'}

\def\FTP{http://www.cse.ohio-state.edu/\string~gurari/tpf/}

\input tex4ht-cpright

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\<htcmd.c\><<<
/* htcmd.c (`version), generated from `jobname.tex
  Copyright 2009-2020 TeX Users Group
  Copyright `CopyYear.1996. Eitan M. Gurari
  `<TeX4ht copyright`> */
`<htcmd.h`>
`<defines`>
`<vars`>
`<header functions`>
`<functions`>
`[
int `<CDECL`> main(argc, argv)
      int  argc`;
      Q_CHAR **argv
;{ `<main's vars`>
  `<set signals`>
#ifdef PLATFORM
  (IGNORED) printf("htcmd.c (`version %s)\n",PLATFORM);
#else
  (IGNORED) printf("htcmd.c (`version)\n");
#endif
 `<main's init`>
 `<command = job args`>
 `<make system call`>
  return 0;
}
>>>



\<htcmd.h\><<<
/* **********************************************
   Compiler options                            *
   (uncommented | command line)                *
------------------------------------------------*
       Clasic C (CC)             default
#define ANSI                      ansi-c, c++
#define DOS_C
#define HAVE_STRING_H             <string.h>
#define HAVE_DIRENT_H             <dirent.h>
#define HAVE_SYS_NDIR_H           <sys/ndir.h>
#define HAVE_SYS_DIR_H            <sys/dir.h>
#define HAVE_NDIR_H               <ndir.h>
#define HAVE_IO_H                 <io.h>
#define HAVE_UNISTD_H             <unistd.h>
#define WIN32
#define KPATHSEA
#define SYSTEM_FUNCTION_OK
#define CDECL                    ..........
#define BCC32                    bordland c++

*************************************************
   Tex4ht variables                            *
   (uncommented | command line)                *
----------------------------------------------- */
`<h-defines`>
/* ******************************************** */
`<define MSVC-1-52`>
`<bordland: bcc32 -DBCC32 htcmd`>
`<bordland: bcc -DBCC tex4ht`>
`<DJGPP`>
#ifdef DOS_C
#define DOS
#endif
#ifdef DOS
#define DOS_WIN32
#ifndef HAVE_STRING_H
#define HAVE_STRING_H
#endif
#endif
#ifdef WIN32
#define DOS_WIN32
#endif
`<h-defines DOS-WIN32`>
`<h-defines KWIN32`>
`<h-include`>
`<h-defines 2`>
>>>

\<htcmd.h\><<<
#ifdef DOS
#define PROTOTYP
#endif
#ifdef ANSI
#define PROTOTYP
#endif
#ifdef KWIN32
#define PROTOTYP
#endif
>>>


\<htcmd.h\><<<
#ifdef KPATHSEA
#ifdef WIN32
#undef CDECL
#define CDECL                     __cdecl
#else
#define CDECL
#endif
#endif
>>>

\<h-defines KWIN32\><<<
#ifdef KPATHSEA
#ifdef WIN32
#define KWIN32
#endif
#endif
>>>



\''open(file, ..._FLAGS)': All
text files should be opened with "r" or "w"; all binary files with "rb"
or "wb". This is the portable way and will work both under Unix and DOS;
as Unix doesn't distinguish between text and binary files, its compilers
will simply ignore the "b" part.

 On the subject of the .lg file: you open the tex4ht.env file in binary
mode ("rb"), which results in strange line endings in the .lg file
(CR/CR/LF). Changing the mode to "r" fixes this.


\<htcmd.h\><<<
#if defined(DOS_WIN32) || defined(__MSDOS__)
#define READ_BIN_FLAGS "rb"
#define READ_TEXT_FLAGS "r"
#define WRITE_BIN_FLAGS "wb"
#define WRITE_TEXT_FLAGS "w"
#else
#define READ_BIN_FLAGS "r"
#define READ_TEXT_FLAGS "r"
#define WRITE_BIN_FLAGS "w"
#define WRITE_TEXT_FLAGS "w"
#endif
>>>

\<defines\><<<
#define Q_CHAR char
#define U_CHAR char
#define C_CHAR char
#define Q_NULL (Q_CHAR *) 0
#define U_NULL (U_CHAR *) 0
#define C_NULL (C_CHAR *) 0
>>>


\<defines\><<<
#define IGNORED void
>>>

\<defines\><<<
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
>>>



\<defines\><<<
#ifdef PROTOTYP
#define VOID void
#define ARG_I(x) x
#define ARG_II(x,y) x,y
#define ARG_III(x,y,z) x,y,z
#define ARG_IV(x,y,z,w) x,y,z,w
#define ARG_V(x,y,z,w,u) x,y,z,w,u
#else
#define VOID
#define ARG_I(x)
#define ARG_II(x,y)
#define ARG_III(x,y,z)
#define ARG_IV(x,y,z,w)
#define ARG_V(x,y,z,w,u)
#endif
>>>



\<defines\><<<
struct sys_call_rec{
 Q_CHAR * filter;
 struct sys_call_rec *next;
};
>>>


\<vars\><<<
static BOOL system_yes;
>>>


\<defines\><<<
struct script_struct{
 Q_CHAR *command;
 struct script_struct *next;
};
>>>

\<defines\><<<
#define NULL_SCRIPT (struct script_struct *) 0
>>>


\SubSection{Signals}

\<h-include\><<<
#include <signal.h>
>>>

\<header functions\><<<
static void
`<CDECL`>
sig_err(ARG_I(int));
>>>




\<functions\><<<
`[
static void
`<CDECL`>
sig_err(s)  int s
;{
 (void) signal(s,SIG_IGN);  `%ignore the signal`%
 switch( s ){
#ifdef SIGSEGV
   case SIGSEGV: err_i(2);
#endif
   case SIGFPE : err_i(3);
#if defined(SIGINT) && !defined(WIN32)
   case SIGINT : err_i(4);
#endif
 }
 `<DJGPP signals`>
}
>>>




Forgetting \`'_pascal' and \`'_cdecl' modifiers: Each C function may
be either \`'_pascal' or \`'_cdecl'. This modifier defines how
parameters are passed to it. Default for Smalltalk definition is
\`'_cdecl'. Default for C functions depends on compiler settings, and
you can use other types uncompatible with Smalltalk. In Windows API
16-bit functions are \`'_pascal' and 32-bit \`'_cdecl'.



\<CDECL\><<<
#ifdef CDECL
CDECL
#endif
>>>




\<set signals\><<<

#ifdef SIGSEGV
 (void) signal(SIGSEGV,sig_err);
#endif
 (void) signal(SIGFPE,sig_err);
#ifdef KWIN32
 `<KWIN32 signals`>
#else
#ifdef SIGINT
 (void) signal(SIGINT,sig_err);    `%Control-c, user interrupt`%
#endif
#endif
>>>



SIGFPE is handled by the C library, SIGSEGV too but not generated by
the system, so it does nothing but is harmless

SetConsoleCtrlHandler is need to catch Ctrl+C and Ctrl+Break under
Windows, SIGINT is not generated by the system.

\<KWIN32 signals\><<<
SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE);
>>>



SIGSEGV, SIGILL, SIGTERM not implemented in MS-DOS. They are supplied just for
compatibility. Looks like that SIGINT is defined for windows but not for dos.

\<vars\><<<
static int system_return;
>>>

\<main's vars\><<<
int i;
BOOL slash, dslash;
char *in_command, *command, *p, *q;
>>>

\<command = job args\><<<
 in_command = (char *) malloc(1024);
 command = (char *) malloc(1024);
 in_command[0] = '\0';
 `<kpathsea arg 0`>
 if( argc == 1 ){ bad_arg; }
 slash = eq_str(argv[1],"-slash") ;
 dslash = eq_str(argv[1],"-dslash") ;
 for(i=1+slash+dslash; i<argc; i++){
    (IGNORED) printf("%s ", argv[i]);
    (IGNORED) strct(in_command,argv[i]);
    (IGNORED) strct(in_command," ");
 }
 (IGNORED) printf("\n");
>>>


\<make system call\><<<
p = in_command;
q = command;
do{
 if( (*p != '"' ) && (*p != '\'' ) && (*p != '``' ) ){
   if(slash && (*p == '/')) {
     *(q++) = '\\';
   }
   else if(dslash && (*p == '/')) {
     *(q++) = '\\';
     *(q++) = '\\';
   }
   else { *(q++) =  *p;  }
 }
} while (*(p++) != '\0');
(IGNORED) call_sys(command);
>>>


\SubSection{PreProcessor Directives}


Symantec C++ for wid95:
\''sc htcmd.c -mn -o+time -WA -3 -a8 -c -D_CONSOLE=1 -ohtcmd.obj'






\<bordland: bcc32 -DBCC32 htcmd\><<<
#ifdef BCC32
#define WIN32
#define ANSI
#define HAVE_IO_H
#define HAVE_STRING_H
#define PLATFORM "ms-win32"
#endif
>>>

%

\<bordland: bcc -DBCC tex4ht\><<<
#ifdef BCC
#define DOS_C
#define ANSI
#define HAVE_IO_H
#define PLATFORM "ms-dos"
#endif
>>>


\<h-include\><<<
#include <stdio.h>   `% EOF, FILE `%
#include <stdlib.h>  `% EXIT_FAILURE `%
>>>



 Under ANSI C, all malloc stuff is declared in \`'<stdlib.h>' (which you
also include), hence this non-standard header is redundant.





\<h-include\><<<
#ifdef HAVE_STRING_H
#include <string.h>
#endif
>>>






\<h-defines DOS-WIN32\><<<
#ifdef DOS_WIN32
#define STRUCT_DIRENT
#endif
>>>


\<h-include\><<<
#ifdef HAVE_DIRENT_H
`<needs dirent.h`>
#else
#ifndef STRUCT_DIRENT
#define STRUCT_DIRECT
#endif
`<needs simulated dirent.h`>
#endif
>>>



\<needs dirent.h\><<<
#include <dirent.h>
>>>


\<needs simulated dirent.h\><<<
#ifdef HAVE_SYS_NDIR_H
#include <sys/ndir.h>
#endif
#ifdef HAVE_SYS_DIR_H
#include <sys/dir.h>
#endif
#ifdef HAVE_NDIR_H
#include <ndir.h>
#endif
>>>


REPLACE EXIT with somthing that DOS also accept.







\SubSection{KPATHSEA}

\<h-defines 2NO\><<<
`<h-include before KPATHSEA`>
#ifdef KPATHSEA
#ifndef HAVE_STRCHR
#define  strchr  index
#endif
#ifndef HAVE_STRRCHR
#define  strrchr  rindex
#endif
#include <kpathsea/config.h>
#include <kpathsea/c-errno.h>
#include <kpathsea/c-ctype.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/c-pathmx.h>
#include <kpathsea/proginit.h>
#include <kpathsea/tex-file.h>
#include <kpathsea/tex-make.h>
#include <signal.h>
#if !defined(_AMIGA) && !defined(WIN32)
#include <sys/time.h>
#endif
#include <fcntl.h>
#include <setjmp.h>
#endif `%/* KPATHSEA */`%
`<h-include after KPATHSEA`>
>>>

\<h-defines 2\><<<
`<h-include before KPATHSEA`>
#ifdef KPATHSEA
#include <kpathsea/config.h>
#include <kpathsea/c-errno.h>
#include <kpathsea/c-ctype.h>
#include <kpathsea/c-fopen.h>
#include <kpathsea/c-pathmx.h>
#include <kpathsea/proginit.h>
#include <kpathsea/tex-file.h>
#include <kpathsea/tex-make.h>
#include <signal.h>
#if !defined(_AMIGA) && !defined(WIN32)
#include <sys/time.h>
#endif
#include <fcntl.h>
#include <setjmp.h>
#endif `%/* KPATHSEA */`%
`<h-include after KPATHSEA`>
>>>


The \`'__cdecl' is defined in KPATHSEA: kpathsea/c-protos.h
is defined to nothing for compilers
other than MS.







\<DJGPP\><<<
#ifdef __DJGPP__
#define DOS_WIN32
#define ANSI
#endif
>>>




\<DJGPP signals\><<<
#ifdef __DJGPP__
 if (s != SIGINT && s != SIGQUIT)
   exit(EXIT_FAILURE);
#endif
>>>



\<h-include before KPATHSEA\><<<
#ifndef __DJGPP__
`<h-include near KPATHSEA`>
#endif
>>>



The following is because \`'<unistd.h>
defines F_OK in DJGPP'.

\<h-include after KPATHSEA\><<<
#ifdef __DJGPP__
`<h-include near KPATHSEA`>
#endif
>>>

\<h-include near KPATHSEANO\><<<
#ifndef F_OK
#ifdef DOS_WIN32
#define  F_OK 0               `% does file exist `%
#endif
#ifndef DOS_WIN32
#define HAVE_UNISTD_H
#endif
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
>>>

\<h-include near KPATHSEA\><<<
#ifndef F_OK
#ifdef DOS_WIN32
#define  F_OK 0               `% does file exist `%
#endif
#ifndef KPATHSEA
#ifndef DOS_WIN32
#define HAVE_UNISTD_H
#endif
#endif
#endif
#ifdef HAVE_IO_H
#include <io.h>
#endif
#ifndef KPATHSEA
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#endif
>>>


\<defines\><<<
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef BOOL
#define BOOL int
#endif
>>>




\<defines\><<<
#define bad_arg            err_arg(0)
#define bad_mem             err_i(1)
>>>






\<header functions\><<<
static void err_i( ARG_I(int) );
>>>

\<functions\><<<
`[
static void err_i(n)      int  n

;{  (IGNORED) fprintf(stderr,"--- error --- ");
   (IGNORED) fprintf(stderr, "%s", warn_err_mssg[n]);
  exit(EXIT_FAILURE);
}
>>>



\<header functions\><<<
static void err_arg( ARG_I(int) );
>>>

\<functions\><<<
`[
static void err_arg(n)      int  n

;{  (IGNORED) fprintf(stderr,"--- error --- ");
   (IGNORED) fprintf(stderr, "%s", warn_err_mssg[n]);
  exit(EXIT_FAILURE);
}
>>>



\<vars\><<<
static C_CHAR *warn_err_mssg[]={ `<warn and err messages`> "" };
>>>



\<warn and err messages\><<<
"\n---------------------------------------------------------------\n\
htcmd optional-flag command-line\n\n\
  optional-flag:\n\
       -slash     translate '/' into '\\'\n\
       -dslash    translate '/' into '\\\\'\n\n\
Example: \n\
  htcmd t4ht name -d/WWW/temp/ -etex4ht-32.env -m644\n\
---------------------------------------------------------------\n"
>>>





\<system exist?\><<<
#ifdef SYSTEM_FUNCTION_OK
0
#else
system( yes ) != 0
#endif
>>>








\<header functions\><<<
static void call_sys(ARG_I(Q_CHAR *));
>>>

\<functions\><<<
`[
static void call_sys(command)  Q_CHAR * command
;{
  if( *command ){
     (IGNORED) printf("htcmd calls: %s\n", command);
     system_return = system_yes?  (int) system(command) : -1;
     (IGNORED) printf("%shtcmd returns: %d\n",
           system_return? "--- Warning --- " : "", system_return );
  }
}
>>>





strcat should be in string.h, but c++ doesn't find it there.
We use it just for concatenating an extension of
file name. Should have the interface
\`'char *strcat( ARG_II(C_CHAR *, const Q_CHAR *) );'.

\<header functions\><<<
static void strct( ARG_II(C_CHAR *, C_CHAR *) );
>>>

\<functions\><<<
`[
static void strct( str1, str2 )
    Q_CHAR * str1`;
    Q_CHAR * str2

;{   Q_CHAR * ch;
  ch = str1 + (int) strlen(str1);
  (IGNORED) strcpy( ch, str2 );
}
>>>



\<main's init\><<<
{                   C_CHAR   *yes = NULL;
 system_yes = (`<system exist?`>);
}
>>>

\<defines\><<<
#define eq_str(x,y) (!strcmp(x,y))
>>>






%----------------------------------------------------

\OutputCodE\<htcmd.c\>


\bye