Chapter 1
Flow of Program

   1.1 Preamble
      MSVC-1-52-DOS
      KPATHSEA Windows
      DJGPP
      Compatibity
      Signals
   1.2 Kpathsea
   1.3 Outline
      Main’s Body
      Utilities
   1.4 Installers and Makefiles
   1.5 Command Line Switches
   1.6 I/O Files
      Open Input
      Open Root Html File
      Close Output
      Get Input-File Length
   1.7 Coding Hints

<..TeX4ht copyright..>
 %
 % This work may be distributed and/or modified under the
 % conditions of the LaTeX Project Public License, either
 % version 1.3c of this license or (at your option) any
 % later version. The latest version of this license is in
 %   http://www.latex-project.org/lppl.txt
 % and version 1.3c or later is part of all distributions
 % of LaTeX version 2005/12/01 or later.
 %
 % This work has the LPPL maintenance status "maintained".
 %
 % The Current Maintainer of this work
 % is the TeX4ht Project <http://tug.org/tex4ht>.
 %
 % If you modify this program, changing the
 % version identification would be appreciated.-_-_-

<..TeX4ht copywrite..>
 |<TeX4ht copyright|>
 \immediate\write-1{version |version}
 -_-_-

1.1 Preamble

A command-line program running in the console environment of the operating system (MS-DOS, MS-DOS window of Windows 3.1, Unix shell, etc). The input is a heavily specialized DVI file. The main output is the HTML/XML and ‘.css’, also ‘.lg’, ‘.idv’, and ‘.tmp’.

<..tex4ht.c..>
 /* tex4ht.c (2014-07-21-21:39), generated from tex4ht-c.tex
    Copyright (C) 2009-2012 TeX Users Group
    Copyright (C) 1996-2009 Eitan M. Gurari
 <.TeX4ht copyright.> */
 <.tex4ht.h.>
 -_-_-

<..tex4ht.h..>
 /* Compiler options (uncommented | command line), as comments:
 
        Classic 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 CDECL                     .......
 #define BCC32                     bordland c++
 
 *************************************************
     Tex4ht variables                            *
     (uncommented | command line)                *
 ----------------------------------------------- */
 <.h-defines.>
 /* ******************************************** */
 <.define MSVC-1-52.>
 <.bordland: bcc32 -DBCC32 tex4ht.>
 <.bordland: bcc -DBCC -mh tex4ht.>
 <.DJGPP.>
 #ifdef DOS_C
 #define DOS
 #endif
 #ifdef DOS
 #define DOS_WIN32
 #define HAVE_STRING_H   <string.h>
 #endif
 #ifdef WIN32
 #define DOS_WIN32
 #ifndef KPATHSEA
 #define HAVE_STRING_H   <string.h>
 #endif
 #endif
 <.h-defines DOS-WIN32.>
 <.h-defines KWIN32.>
 <.h-include.>
 <.h-defines 2.>
 -_-_-

<..bordland: bcc32 -DBCC32 tex4ht..>
 #ifdef BCC32
 #define DOS_WIN32
 #define ANSI
 #define HAVE_DIRENT_H
 #define PLATFORM "ms-win32"
 #endif
 -_-_-

The ‘-mh’ below calls for ‘Huge Memory Model’.

<..bordland: bcc -DBCC -mh tex4ht..>
 #ifdef BCC
 #define DOS_C
 #define ANSI
 #define HAVE_DIRENT_H
 #define PLATFORM "ms-dos"
 #ifndef PATH_MAX
 #define PATH_MAX 256
 #endif
 #endif
 -_-_-

[more]

microsoft visual c options: msdos application (.exe), large, ss=sd

#define MSVC_1_52_DOS 
#define MSVC_1_52_DOS_LIB         not fully implemented 
------------------------------------------------------------ 
    End options --- Start comments                         * 
------------------------------------------------------------ 
MSVC_1_52_DOS:                                             * 
   MS-DOS appl (project type), release (buld mode),        * 
     huge, ss==ds, 80286, no debug                         * 
   no sub directories (missing opendir,closedir, readdir)  * 
MSVC_1_52_DOS_LIB:                                         * 
   as above, but opendir,closedir, readdir compiled        * 
   with tex4ht                                             * 
------------------------------------------------------------ 
    End comments 

<..h-include..>
 #ifdef KPATHSEA
 #include <kpathsea/config.h>
 #endif
 #include <stdio.h>    EOF, FILE 
 #include <stdlib.h>   EXIT_FAILURE 
 -_-_-

<..defines..>
 #ifndef EXIT_FAILURE
 #define EXIT_FAILURE 1
 #endif
 -_-_-

<..h-include..>+
 #ifdef HAVE_STRING_H
 #include <string.h>
 #endif
 -_-_-

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

MSVC-1-52-DOS

<..define MSVC-1-52NO..>
 #ifdef MSVC_1_52_DOS_LIB
 #define  MSVC_1_52_DOS
 #endif
 #ifdef MSVC_1_52_DOS
 #define DOS
 #define NOSUBDIR
 #endif
 #ifdef MSVC_1_52_DOS_LIB
 #undef NOSUBDIR
 #endif
 -_-_-

<..if not-def MSVC-1-52NO..>
 #ifndef MSVC_1_52_DOS
 -_-_-

<..endif not-def MSVC-1-52NO..>
 #endif
 -_-_-

KPATHSEA Windows

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

Here are the promised patch. However I have not yet tested it very much. It is unlikely that I test it with non-kpathsea setting. At least the patch compiles in both kpathsea and non-kpathsea setting. The following patch is very similar to some code in kpathsea / web2c.

<..h-include..>+
 #ifdef WIN32
 #ifdef KPATHSEA
 #undef CDECL
 #define CDECL                     __cdecl
 #else
 #include <windows.h>
 #endif
 #else
 #ifdef KPATHSEA
 #define CDECL
 #endif
 #endif
 -_-_-

<..if not-WIN32..>
 #ifndef WIN32
 -_-_-

<..endif not-WIN32..>
 #endif
 -_-_-

<..header functions..>
 #ifdef WIN32
 static BOOL sigint_handler(ARG_I(DWORD));
 #endif
 -_-_-

<..functions..>
 #ifdef WIN32
 
 
 
 static BOOL  sigint_handler(dwCtrlType)  DWORD dwCtrlType
 ;{
   <.avoid warning of unused dwCtrlType.>
   err_i(32);
   return FALSE;       return value obligatory 
 }
 #endif
 -_-_-

<..avoid warning of unused dwCtrlType..>
 if( dwCtrlType ){ (IGNORED) printf(" "); }
 -_-_-

<..CDECL..>
 #ifdef CDECL
 CDECL
 #endif
 -_-_-

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’.

The following Shared across recursive calls, it acts like a stack.

<..vars..>
 #ifdef WIN32
 static U_CHAR dirname[PATH_MAX];
 #endif
 -_-_-

Recursive directory search relies on some Windows API similar to opendir/readdir

<..file = search WIN32 subdir (name,str)..>
 {
     WIN32_FIND_DATA find_file_data;
     HANDLE hnd;
     int proceed;
     (IGNORED) strcpy((char *) dirname, (char *) str);
     strct(dirname, "/*.*");        "*.*" or "*" -- seems equivalent. 
     hnd = FindFirstFile(dirname, &find_file_data);
     if (hnd != INVALID_HANDLE_VALUE) {
       <.valid WIN32 handle.>
     }
 }
 -_-_-

<..valid WIN32 handle..>
 proceed = 1;
 while (proceed) {
   if( !eq_str(find_file_data.cFileName, ".")  &&
       !eq_str(find_file_data.cFileName, "..") )
     {
       (IGNORED) strcpy((char *)  str+n, (char *) find_file_data.cFileName );
       str[n-1] = dir_path_slash(str);
       if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
   if( (file = search_file_ext(name, str, flags)) != NULL ){
     FindClose(hnd);
     return file; }
       }
     }
   proceed = FindNextFile(hnd, &find_file_data);
 }
 FindClose(hnd);
 -_-_-

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);
 -_-_-

DJGPP

 
        * tex4ht.c [__DJGPP__] (ANSI, DOS_GIF_FILE): Define. 
        (LSTAT): Define to stat for every system that doesn’t define 
        S_ISLNK. 
        (WRITE_BIN_FLAGS, READ_BIN_FLAGS): Use binary mode with DJGPP. 
        (dos_file_names): New variable. 
        [WIN32] (sigint_handler): Add missing semi-colon in prototype 
        declaration. 
        (sig_err): If got fatal signal other than SIGINT or SIGQUIT, don’t 
        return to caller, since the program will be aborted otherwise. 
        (search_file_ext): Allow use of both forward- and back-slashes on 
        DOS and Windows platforms. 
        (insert_ch) [DOS_GIF_FILE]: Only use butchered file name if long 
        file names aren’t supported (dos_file_names is TRUE). 
        (main) [KPATHSEA]: If input is from stdin which is not a console 
        device, switch it to binary mode.  Set dos_file_names to TRUE for 
        all DOS platforms, FALSE on Unix and WIN32, and compute at runtime 
        for DJGPP.  Simplify logic of finding the init file by pushing 
        HOME=C: into environment if $HOME isn’t defined on DOSISH systems. 
        Only use butchered file names for GIF files if long file names 
        aren’t supported (dos_file_names is TRUE). 

<..DJGPP..>
 #ifdef __DJGPP__
 #define DOS_WIN
 #define ANSI
 #ifndef HAVE_STRING_H
 #define HAVE_STRING_H 1
 #endif
 #endif
 -_-_-

<..vars..>+
 static BOOL dos_file_names =
 #ifdef DOS_GIF_FILE
   TRUE
 #else
   FALSE
 #endif
 ;
 -_-_-

Set dos_file_names to TRUE for all DOS platforms, FALSE on Unix and WIN32, and compute at runtime for DJGPP.

<..DJGPP gif names for pictorial symbols..>
 #if !defined(DOS_GIF_FILE) && !defined(WIN32) && defined(__DJGPP__)
    dos_file_names = !_use_lfn(NULL);
 #endif
 -_-_-

<..extra options..>
 switch( *(p+2) ){
   case ’s’:{   dos_file_names = TRUE;  break; }
    default:{ bad_arg; }
 }
 -_-_-

 
 > The diffs are attached below.  The first hunk is because HAVE_STRING_H is 
 > already defined by c-auto.h that’s generated by configure, and GCC 
 > complained about redefinition.  The second hunk just moves the call to 
 > _use_lfn to a place where the variable "name" is defined.  _use_lfn needs 
 > an actual file name as argument, because the support for long file names 
 > is determined dynamically for each filesystem.  (There can be cases where 
 > you run on Windows 9X, where DJGPP supports long file names, but one or 
 > more of the file names passed to tex4ht reside on some networked drive 
 > mounted with a network client which doesn’t support long file names.) 
 
 
 
 
> Now, do we want tex4ht to propose a long and a short name for each 
> output file, and determine in each case which of the two names to 
> assign according to whether ‘use_lfn(name)’ accepts the long name? 
 
That’s what I had in mind, yes. 
 
The philosophy behind that is that DJGPP executables should use long 
file names whenever they are available.  However, given that there are 
several different filesystems accessible from the machine (via a 
network), long names might be supported by some of these filesystems, 
but not by others.  So the DJGPP version needs to decide whether or 
not to use the long name for every command-line argument it processes, 
since each such argument can belong to a different filesystem. 
 
For example, suppose tex4ht.exe is invoked like this: 
 
             tex4ht c:/foo/bar/baz.dvi d:/dvi/xyz.dvi 
 
If the C: drive supports long file names, but D: does not (because it 
is mounted by a network software which doesn’t support long file 
names), my intent was that tex4ht will behave differently with each 
file. 
 
 
This feature turns out to be too expensive to utilize in tex4ht.c. 
The problem is that tex4ht first creates the html files from the dvi 
source, and during this phase it determines which pictorial symbols 
are needed. The gif files of the pictorial symbols get their names 
during this phase. However, the gif files themselves are created only 
at the end of the compilation, after all the names have been already 
determined and used. 
 
 
Anyway, the fallback should be to determine the value of dos_file_names 
(sp?) once, in the beginning of ‘main’, by calling _use_lfn(NULL).  This 
checks long file name support by the default filesystem, which is usually 
a good indication of other filesystems as well. 
 
 
 
Corrections to my previous email: 
 
In the first phase, tex4ht.c extracts the html code from the dvi file 
and, along this process, determines the names of the gif files for the 
pictorial symbols in use.  The following code fragement is responsible 
for getting the names. 
 
   if( !dos_file_names ){ 
      print_f(font_tbl[cur_fnt].name); 
      if( mag == 10 )  (IGNORED) sprintf(str, GIF_I,   design_ch, gif); 
      else             (IGNORED) sprintf(str, GIF_II,  mag, design_ch, 
   gif); 
   } 
 
In the second phase, tex4ht.c creates a dvi page for each of the 
pictorial symbols in use, places the code in the idv file, and puts in 
the lg file requests for translating the dvi pages into gif files of 
the specified names.  The file names are provided by the following 
code. 
 
   if( !dos_file_names ){ 
      if( mag == 10 ) (IGNORED) sprintf(str, ‘‘%s-%x%s’’, 
                              font_tbl[cur_fnt].name, ch, gif); 
      else            (IGNORED) sprintf(str, ‘‘%s-%x-%x%s’’, 
                              font_tbl[cur_fnt].name, mag, ch, gif); 
   } 
 
tex4ht.c never gets to create the gif files.  Instead, t4ht.c scans 
the lg file, and use that information to invoke auxiliary tools for 
translating the dvi pages into gif files. 
 
 
 
Added also a command line switch -xs to allow forcing of short names 
for the gif files. 

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

Compatibity

 > The style file provides a set of commands for requesting html code. 
 > The user may insert these commands to the source code, and tex4ht will 
 > use them to create the desired output.  I placed a more detailed 
 > overview with examples in 
 >       http://www.cse.ohio-state.edu/~gurari/temp/XXX/ 
 
  I’ve downloaded the Essential Tex example, and managed to convert it 
(sort of). There are a few problems with file name lengths - I had to 
rename the file to es.tex to get it to be processed properly. According 
to the .lg file I should have a lot of es.idv[xx] files; since DOS only 
supports 3 character extentions, they had all overwritten each other 
(truncating the extention to .idv), so I only had one file. Trying to 
view this file made my driver complain that it was corrupt (it lacked a 
postamble). 
 
  Basically, most of the functionality seems to work under DOS, but the 
file naming conventions appear to be a problem. If you want a more 
detailed report of the problems, let me know. 
 
 > I have no problems dealing with C code, but I’m not familiar with the 
 > different standards (including ANSI C) and libraries that exist 
 > around.  I’ll need to overcome this deficiency to make tex4ht.c a 
 > portable utility. 
 
  I’ve been following comp.lang.c for quite a while now, which focuses 
strongly on portable (ANSI) C, so I have some insight in that. If you 
solely use the ANSI C library functions (which should be possible, I 
think), you don’t need to worry about portability - any conforming 
compiler can generate the code. For example, I noticed that your code 
includes: 
 
 
  Under ANSI C, all malloc stuff is declared in <stdlib.h> (which you 
also include), hence this non-standard header is redundant. 
 
  Looking a bit better at the source code, I found that I could rid 
myself of all the prototype problems by defining ARG. For ANSI, this 
should be the default. If you really want to go for ANSI, you can get 
rid of all these ARG_I macro’s and fully and unconditionally prototype 
everything. 
 
All of the "const is long" warnings can be fixed by appending a "L" 
after all constants bigger than 32767. The "conversion may loose 
significant digits" warnings appear to be related with indexing arrays 
with longs - I haven’t figured this one out yet, as far as I know ANSI 
allows this. (DOS compilers generally don’t support it, though - I can 
just turn off this warning). 
 
  A few warnings result from using an assignment inside an if-clause, 
mostly with file opening code (e.g. "if(name = fopen(stuff)){file is 
open}"). Changing this to an explicit comparison to NULL ("if((name = 
fopen(stuff)) != NULL)") kills the warnings while allowing the compiler 
to warn you when you typed "=" where you ment "==". 
 
  One last thing I noticed: after other attempts at opening "tex4ht.env" 
have failed, you try to open "C:\.tex4ht". Since DOS doesn’t allow files 
with no name (only an extention), and the maximum size of the extention 
is 3 chars anyway, this will always fail - so this code can be deleted. 
 
 > I’ll get an ANSI C compiler for my PC, and will fix tex4ht.c to deal 
 > also with that standard.  I’ll might ask your advice regarding 
 > searching directories and files on pc’s, but if this will be the case 
 > I’ll prepare a small toy example capturing the features I need. 
 
  You may be used to stuff like opendir/readdir/closedir; I believe 
there is code in the snippets maintained by Bob Stout that emulates 
these calls under DOS. If you place this stuff in a separate module, 
your main code can remain portable (it is a good idea to separate the 
non-portable stuff from the portable code). 
 
  Note that a port of gcc to DOS exists (djgpp), which eliminates many 
of the porting problems. It still would be nice if it compiled 
error-free on my native DOS compiler, though. 
 
  Good - I’m glad that I’m of some help. The code snippet you sent me 
compiled without a single warning here, so you’re on the right track 
(although stuff like stat() isn’t ANSI, it appears supported by a lot of 
compilers). 
 
  I compiled the source with the defines DOS and ANSI - and most of it 
worked. You forgot the terminating quote for "tex4ht.env on line 1715. I 
also get warnings that denominator and numerator are not being used 
(only assigned to) and, from the source, the warning appears to be 
correct. 
 
  If I turn on my compilers ANSI flag, I have a few problems. First, 
your function declarations are still in K&R style C. Although ANSI 
allows that, it prohibits type checking, and gives some problems with 
argument promotion. Specifically, the function insert_ch_map() gives 
problems. Your declaration looks like this (I reformatted it a bit for 
readability ;-): 
 
void  insert_ch_map(ch, tag) 
  char ch; 
  BOOL tag; 
{ /* etc */ 
 
  Changing this to the normal ANSI definition shuts up my compiler: 
 
void  insert_ch_map(char ch, BOOL tag) { /* etc */ 
 
  I suggest that you change your other function definitions to ANSI 
style too (if you still want to go for ANSI, that is). 
 
  Another problem I ran into is that _fileno is unavailable to both 
compiler and linker if I turn on ANSI compilation. I checked where you 
use it, and it is in only one place, to find the file length of the DVI 
file. Your code: 
 
  struct STSTAT temp; 
  (IGNORED) fstat (fileno(dvi_file), &temp); 
  file_len = (long) temp.st_size; 
  if( (file_len % 4) != 0 )  bad_dvi; 
 
If you change this to use ftell and fseek, you’ll have gained ANSI 
compatibility (and therewith portability). I tried the following code 
instead of yours: 
 
  long  curr_pos; 
 
  curr_pos = ftell(dvi_file); 
  fseek(dvi_file, 0, SEEK_END); 
  file_len = ftell(dvi_file); 
  fseek(dvi_file, curr_pos, SEEK_SET); 
  if( (file_len % 4) != 0 )  bad_dvi; 
 
  To the best of my nowledge, this works exactly like your code (I 
tested it). My executable is compiled with this code. 
 
  I’ve found other non-ANSI stuff that you may want to remove; if you’d 
like me to check for it (and, if I can, suggest an ANSI alternative), 
let me know. I’ve found at least access() - I haven’t looked into how to 
do that portably. 
 
 > With the new versions of the tools,  and the parameter ‘htm’ (instead of 
 > ‘html’) in \Preamble, the full name gentle.tex can be used. 
 
  Yes, this appears to be working now. 
 
 > A line of the form 
 
 >      -+- needs -+- es.idv[xx] ==> abc.gif -+- 
 
 > in the .lg file asks that the xx’th page of es.idv will be translated 
 > into a gif picture and be stored in file abc.gif. 
 
  OK, I misunderstood that. I will hold off looking into the picture 
translation for a bit - but this seems like a job for perl. There is a 
DOS port of perl, and I’m just familiarizing myself with it. I don’t 
know if the port is able to launch sub-processes. If not, I could 
probably come up with an awk or perl script that creates a batch file to 
do the job. (Requiring awk may be nicer than requiring perl, since the 
DOS port of awk is only a little over 90 KB, while perl is seven times 
as large). Alternatively, you could perhaps change the format of the lg 
file a bit, to contain lines like: 
 
convert es.idv xx abc.gif 
 
i.e., provide the required information as dvi file, page number, and 
output filename on the commandline of "convert" (or however you want to 
call it). This could that be used almost without effort as shell script 
or batch file. 
 
 > After getting your last email, I bought Turbo C++ 4.5 for windows (I 
 > couldn’t find one for dos without reaching to a very fat system). I 
 > tried the attached program in different modes, including ANSI C, and 
 > to my surprise opendir/readdir/closedir worked fine. 
 
  Here too. Strange. Opendir etc is not ANSI, but it is Posix - and 
apparently Borland added some posix stuff to their libraries. I’m not 
sure if you should stick with them or not. I haven’t studied that part 
of your source code yet, so I can’t say if it can be easily ANSIfied. If 
we stick with this, and later you want to port to Apple, Amiga, 
whatever, you’re probably in trouble. 
 
 > That left me even more puzzled to why my version of MSVC doesn’t 
 > support these functions. 
 
  They’re Posix - a Unix standard. Apparently they felt is wasn’t 
appropriate for DOS. 
 
  A few notes on the working of tex4ht.sty: Some of my code doesn’t 
compile because I have \label{}s inside sectioning commands. LaTeX 
itself does allow this. Also, all headings are links to themselves - 
why? 
 
  Below, I included a LaTeX source that both your code and LaTeX2HTML 
can’t seem to translate properly - but then, I hardly know anything of 
the possibilities of tex4ht.sty. Have you started any form of 
documentation yet? (I don’t read TeX, only LaTeX, so looking at the sty 
file myself didn’t help much). 
 
 
 
\documentclass[11pt]{article} 
\usepackage{alltt} 
 
%% Environment to typeset screen text, menus etc. in: verbatim-style 
%% and boxed. 
 
\newsavebox{\scrntxt} 
\newenvironment{boxedfig}[2]% 
 % First argument is width of box, second is caption text 
 { \newcommand{\capt}{#2}% To transport caption to end of environment 
   \begin{minipage}[b]{#1}% 
   \begin{lrbox}{\scrntxt}\begin{minipage}{\textwidth}% 
   \fontsize{10}{11}\selectfont\begin{alltt}% 
 } % 
 { \end{alltt}\end{minipage}\end{lrbox}\setlength{\fboxsep}{3pt}% 
   \framebox[\textwidth][l]{\usebox{\scrntxt}}\caption{\capt}% 
   \end{minipage}% 
 } 
 
\begin{document} 
 
Below you will find two figures. They are boxed neatly, and typeset in a 
fixed-width font of a size independent of the main font size. 
 
\begin{figure}[htb] 
\begin{boxedfig}{0.495\textwidth}{The MBR 1 boot menu\label{bootmenu:1}} 
Please select partition too boot. 
Choose from: 
 
1. 123456789AB 
2. 123456789AB 
3. 123456789AB 
4. 123456789AB 
 
? 
\end{boxedfig}\hfill 
\begin{boxedfig}{0.495\textwidth}{The MBR 2 boot menu\label{bootmenu:2}} 
Please select partition too boot. 
Choose from: 
 
1. 12345678 
2. 12345678 
3. 12345678 
4. 12345678 
 
Boot? 
\end{boxedfig} 
\end{figure} 
 
I want to be able to reference both 
figure~\ref{bootmenu:1} and figure~\ref{bootmenu:2} from my HTML file. 
How to achieve this? 
 
\end{document} 
 

<..defines..>+
 #if INT_MAX < 2147483647L  2^31
 #define LONG L
 #endif
 -_-_-

Lint does not like non-null pointers to be cast. ‘free(void *)’ instead of ‘free()’ will make lint to stop complaining, but is this really the problem. For this function we have a definition ‘void free(void *)’.

1<<20’ should be ‘1L<<20’ for short integer.

Integers on Dos they are just 16 bits!!! Also, ordering of bytes is inconsistence.

<..h-include..>+
 #include <limits.h>  INT_MAX 
 -_-_-

<..defines..>+
 #ifdef LONG
 #define INTEGER long
 #else
 #define INTEGER int
 #endif
 #define U_CHAR char
 -_-_-

string.h:     extern int strlen( ); 
string.h:          extern size_t strlen(char *); 
string.h:          extern size_t strlen(const char *); 
string.h:       extern size_t strlen( ); 
 
void * realloc( void *, size_t) 

<..resplit argv for windows..>
 #ifdef WIN32
   /* The idea here is to split options apart at spaces: a single argument
      "-foo -bar" becomes the two options "-foo" and "-bar".  We need to
      do this for Windows because mk4ht passes this sort of combined
      option in one string to scripts like htlatex.{unix,bat}.  In the
      Unix case, the shell resplits words when calling t4ht and tex4ht,
      so the program see two options.  But this does not happen with the
      .bat; %4, for instance, remains "-foo -bar".  So we fix it here.  */
   if (argc > 2) {
     int  i, nargc;
     char **nargv, **pnargv, **pargv;
 
     nargv = (char **) xmalloc (2 * argc * sizeof (char *));
     pnargv = nargv;
     pargv = argv;
     *pnargv++ = xstrdup (*pargv++);
     *pnargv++ = xstrdup (*pargv++);
     nargc = 2;
 
     for (i=2; i < argc; i++) {
       char *p, *q, *r;
       p = q = *pargv++;
       while (*p ==   || *p == ’\t’) {
         p++;
         q++;
       }
       while (*p !=   && *p != ’\t’ && *p) {
         p++;
         if (*p == ’\0’) {
           *pnargv++ = xstrdup(q);
           nargc++;
         } else if (*p ==   || *p == ’\t’) {
           r = p;
           while (*p ==   || *p == ’\t’)
             p++;
           if (*p == ’-’ || *p == ’\0’) {
             *r = ’\0’;
             *pnargv++ = xstrdup(q);
             nargc++;
             q = p;
           }
         }
       }
     }
 
     nargv[nargc] = NULL;
     argv = nargv;
     argc = nargc;
   }
 #endif
 -_-_-

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(30);
 #endif
     case SIGFPE : err_i(31);
 #if defined(SIGINT) && !defined(WIN32)
     case SIGINT : err_i(32);
 #endif
   }
   <.DJGPP signals.>
 }
 -_-_-

DJGPP:(sig_err): If got fatal signal other than SIGINT or SIGQUIT, don’t return to caller, since the program will be aborted otherwise.

<..set signals..>
 
 #ifdef SIGSEGV
   (void) signal(SIGSEGV,sig_err);
 #endif
   (void) signal(SIGFPE,sig_err);
 #ifdef WIN32
   <.KWIN32 signals.>
 #else
 #ifdef SIGINT
   (void) signal(SIGINT,sig_err);    Control-c, user interrupt
 #endif
 #endif
 -_-_-

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. [more]

Msvc recommends not using printf, but we ignoring this recommendation here with the assumption that the recommendation relates to I/O interrupts that are not considered here.

<..signals messages: 30-32..>
 "Illegal storage address\n", 30 segmentation
 "Floating-point\n",          31 
 "Interrupt with Cntr-C\n",   32 
 -_-_-

1.2 Kpathsea

<..KPATHSEA h-include..>
 #ifdef KPATHSEA
 #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 <kpathsea/variable.h>
 #include <signal.h>
 #if !defined(_AMIGA) && !defined(WIN32)
 #include <sys/time.h>
 #endif
 #include <fcntl.h>
 #include <setjmp.h>
 #endif /* KPATHSEA */
 -_-_-

1.3 Outline

<..tex4ht.c..>+
 <.defines.>
 <.types.>
 <.vars.>
 <.header functions.>
 <.functions.>
 
 int <.CDECL.> main(argc, argv)
        int  argc;
        U_CHAR **argv
 ;{  <.main’s vars.>
    <.resplit argv for windows.>
    <.set signals.>
    <.program signature.>
    <.init traces.>
    <.main’s init.>
    <.main’s body.>
    return 0;
 }
 -_-_-

The operating system claims that ‘Compilation exited abnormally with code 255’ even on cases that come back through return. why? Was this corrected?

<..program signature..>
 (IGNORED) printf("----------------------------\n");
 #ifndef KPATHSEA
 #ifdef PLATFORM
    (IGNORED) printf("tex4ht.c (2014-07-21-21:39 %s)\n",PLATFORM);
 #else
    (IGNORED) printf("tex4ht.c (2014-07-21-21:39)\n");
 #endif
 #else
 #ifdef PLATFORM
    (IGNORED) printf("tex4ht.c (2014-07-21-21:39 %s kpathsea)\n",PLATFORM);
 #else
    (IGNORED) printf("tex4ht.c (2014-07-21-21:39 kpathsea)\n");
 #endif
 #endif
 for(i=0; i<argc; i++){
     (IGNORED) printf("%s%s ", (i>1)?"\n  " : "", argv[i]); }
 (IGNORED) printf("\n");
 -_-_-

Main’s Body

<..main’s body..>
 {      long   file_len;
   <.scan job args.>
   <.find tex4ht.env.>
   <.get from tex4ht.env file.>
   <.file-len = size of file.>
   <.open log file.>
   <.export TEX4HTFONTSET.>
   <.scan postamble.>
   (IGNORED) fclose(dot_file);
 }
 <.scan preamble.>
 <.scan pages.>
 put_char(’\n’);put_char(’\n’);
 <.close active output files.>
 {    <.idv vars.>
   <.extract dvi chunks.> }
 -_-_-

<..vars..>+
 static FILE*  dot_file;
 -_-_-

<..main’s vars..>
 register INTEGER  i;
 int  ch;
 -_-_-

Utilities

<..defines..>+
 #define m_alloc(typ,n) (typ *) malloc_chk((int) ((n) * sizeof(typ)))
 -_-_-

<..header functions..>+
 static void* malloc_chk(ARG_I(int));
 -_-_-

<..functions..>+
 
 static void* malloc_chk( n ) int n
 ;{      void* p;
    if((p = (void *) malloc( (size_t) n)) == NULL ) bad_mem;
    return p;
 }
 -_-_-

<..header functions..>+
 static void* r_alloc(ARG_II(void *, size_t));
 -_-_-

<..functions..>+
 
 static void* r_alloc( q, n )
       void   *q;
       size_t  n
 ;{    void*   p;
    if((p = (void *) realloc( q, (size_t) n)) == NULL) bad_mem;
    return p;
 }
 -_-_-

1.4 Installers and Makefiles

1.5 Command Line Switches

<..scan job args..>
 {      int i;
        U_CHAR *p;
        const U_CHAR *in_name = "", *out_name = "";
   <.kpathsea arg 0.>
   <.DJGPP gif names for pictorial symbols.>
   if( argc == 1 ){ bad_arg; }
   for(i=1; i<argc; i++) {
     if( *( p=argv[i] ) == ’-’ ){ <.scan flaged args.> }
     else in_name = argv[i];
   }
   <.post scan comm ln args.>
   <.open input file.>
   { <.pre open output file.> }
 }
 -_-_-

If ‘strlen() argv[i] ) == 2’ the switch is followed by a space to be deleted when more input is awaited.

<..scan flaged args..>
 if( (int) strlen((char *)  argv[i] ) == 2 ){
    if( ++i == argc ) bad_arg;
 }
 switch( *(p+1) ){
   case ’b’:{ <.get start char-gif from com ln.>     break; }
   case ’c’:{ <.env blocks selector.>  break;}
   case ’e’:{ <.get .env directory from com ln.>break; }
   case ’f’:{ <.get file name wo dir.>break; }
   case ’F’:{ <.get ignored chars.>             break; }
   case ’g’:{ <.get gif-type from com ln.>      break; }
   case ’h’:{ <.trace context.>  break; }
   case ’i’:{ <.get htf font dir from com ln.>  break; }
   case ’l’:{ <.get tex4ht.fls from com ln.>  break; }
   case ’P’:{ <.permission for system calls.>  break; }
   case ’S’:{ <.get gif script from com ln.>    break; }
   case ’s’:{ <.get cascade style sheet data.>    break; }
   case ’t’:{ <.get tfm font dir from com ln.>  break; }
   case ’u’:{ <.get unicode entity representations.>  break; }
   case ’v’:{ <.idv version replacement num.>  break; }
   case ’x’:{ <.extra options.>  break; }
   case ’.’:{ <.default extension.>  break; }
    default:{ bad_arg; }
 }
 -_-_-

The following is to allow for commands ‘htlatex -f/../source/foo.tex’ which draw files from other directories for latex, but use the current directory for tex4ht.c (and t4ht.c). The character immediately after ‘-f’ is a directory indicator character. The ‘-f/’ requests a search for the indicated file to take place in the current directory, not in a remote one.

<..get file name wo dir..>
 p = p + 2;
 in_name = p + (int) strlen((char *)  p );
 while( *in_name != *p ){ in_name--; }
 in_name++;
 -_-_-

Suboptions for ‘-h’.

<..trace context..>
 {
   char trace = *(p+2);
   if (trace == ’A’ || trace == ’e’) { <.context for warn and errs.> }
   if (trace == ’A’ || trace == ’f’) { <.dump htf files.> }
   if (trace == ’A’ || trace == ’F’) { <.trace htf search.> }
   if (trace == ’A’ || trace == ’s’) { <.trace specials in dvi.> }
   if (trace == ’A’ || trace == ’g’) { <.cmd line trace groups.> }
   if (trace == ’A’ || trace == ’v’) { <.dump env file.> }
   if (trace == ’A’ || trace == ’V’) { <.trace env search.> }
   else { bad_arg; }
 }
 -_-_-

The following is incomplete!!!

<..command line options..>
 "improper command line\ntex4ht [-f<path-separator-ch>]in-file[.dvi]\n"
 "   [-.<ext>]            replacement to default file extension name .dvi\n"
 "   [-c<tag name>]       choose named segment in env file\n"
 "   [-e<env-file>]\n"
 "   [-f<path-separator-ch>]        remove path from the file name\n"
 "   [-F<ch-code>]        replacement for missing font characters; 0--255; default 0\n"
 "   [-g<bitmap-file-ext>]\n"
 "   [-h(e|f|F|g|s|v|V)]  trace: e-errors/warnings, f-htf, F-htf search\n"
 "                             g-groups, s-specials, v-env, V-env search, A-all\n"
 "   [-i<htf-font-dir>]\n"
 "   [-l<bookkeeping-file>]\n"
 "   [-P(*|<filter>)]     permission for system calls: *-always, filter\n"
 "   [-S<image-script>]\n"
 "   [-s<css-file-ext>]   default: -s4cs; multiple entries allowed\n"
 "   [-t<tfm-font-dir>]\n"
 "   [-u10]               base 10 for unicode characters\n"
 "   [-utf8]              utf-8 encoding for unicode characters\n"
 "   [-v<idv version>]    replacement for the given dvi version\n"
 "   [-xs]           ms-dos file names for automatically generated gifs\n"
 -_-_-

Line breaks within command lines should be physically given.

1.6 I/O Files

<..defines..>+
 #ifndef PATH_MAX
 #define PATH_MAX 512
 #endif
 -_-_-

  ../html.dir/a.out a -s"--- needs --- %%1.idv[%%2] ==> %%3 --- 
" -b"--- characters --- 

Open Input

<..vars..>+
 static FILE* dvi_file;
 -_-_-

<..main’s init..>
 dvi_file = stdin;
 -_-_-

Below: If input is from stdin which is not a console device, switch it to binary mode.

Warning ‘statement with no effect’ under ‘gcc -Wall’ on non-Windows. This is not a problem; SET˙BINARY is a no-op.

<..open input file..>
 if( *in_name != ’\0’ ){ <.file = non-piped input file.> }
 #ifdef KWIN32
    else if (!isatty(fileno(stdin))) SET_BINARY(fileno(stdin));
 #endif
 -_-_-

<..file = non-piped input file..>
       BOOL tag;
 job_name_n = (int) strlen( in_name );
 job_name = m_alloc(char, job_name_n+6);
 (IGNORED) strcpy((char *) job_name, in_name);
 tag = job_name_n < 3;
 if( !tag ){
    tag = !eq_str( job_name+job_name_n-<.dvi ext name length.>,<.dvi ext name.>);
 }
 if( tag ){
    job_name_n+=<.dvi ext name length.>; (IGNORED) strct(job_name, <.dvi ext name.>);
 }
 if( (dvi_file = fopen(job_name, READ_BIN_FLAGS)) == NULL )
    { <.try jobname with extension.> }
 <.open idv file.>
 -_-_-

<..dvi ext name length..>
 (
   (ext==NULL)? 4 : (int) strlen((char *) ext)
 )
 -_-_-

<..dvi ext name..>
 (
   (ext==NULL)? ".dvi" : ext
 )
 -_-_-

<..vars..>+
 static U_CHAR *ext = NULL;
 -_-_-

<..default extension..>
 ext = p+1;
 -_-_-

The following tries to remove an extension from the filename, before adding the ‘.dvi’ extension. This can help with ht scripts of the form

     $1 $2 
     $1 $2 
     $1 $2 
     tex4ht $2 
     t4ht $2 

in cases that the users insert for ‘$2’ file names with extension.

<..try jobname with extension..>
 {                             int i;
    for(i=job_name_n-5; i; i--){
      if( job_name[i] == ’.’ ){
        job_name[i] = ’\0’;
        job_name_n = i + <.dvi ext name length.>;
        (IGNORED) strct(job_name, <.dvi ext name.>);
        break;
    } }
    if( (dvi_file = fopen(job_name, READ_BIN_FLAGS)) == NULL ){
       warn_i_str(1, job_name); bad_in_file(job_name);
 }  }
 -_-_-

<..vars..>+
 static char* job_name;
 static int   job_name_n;
 -_-_-

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( (char *, const U_CHAR *) );’.

<..header functions..>+
 static void strct( ARG_II(char *, const U_CHAR *) );
 -_-_-

<..functions..>+
 
 static void strct( str1, str2 )
      U_CHAR * str1;
      const U_CHAR * str2
 
 ;{   U_CHAR * ch;
    ch = str1 + (int) strlen((char *) str1);
    (IGNORED) strcpy((char *)  ch, str2 );
 }
 -_-_-

Open Root Html File

<..pre open output file..>
    U_CHAR *name=0;
 if( *out_name == ’\0’ )
   { if( *in_name == ’\0’ ){ <.name = "tex4htput.html".> }
     else                  { <.name = derived from input file name.> }
   }
 else{ <.name = output file from arg list.> }
 no_root_file = name;
 -_-_-

We want to wait with actually opening the file output file until the last minute, to allow a special to change the extension name from the tex file. That last minute is taken to be when a cll to openning ort closing a file occurs, or when output is to be written into the file.

<..open output file..>
 if( no_root_file ){  open_o_file(); }
 -_-_-

<..header functions..>+
 static void open_o_file( ARG_I(void) );
 -_-_-

<..functions..>+
 static void open_o_file(MYVOID)
 {
    <.open root tex4ht file.>
    cur_o_file = root_file = open_html_file(no_root_file);
    no_root_file = (char *) 0;
 }
 -_-_-

<..open root tex4ht file..>
     struct files_rec* p;
 p = m_alloc(struct files_rec, 1);
 if( opened_files != (struct files_rec*) 0 ) opened_files->prev = p;
 p->prev = (struct files_rec *) 0;
 p->next = opened_files;     opened_files = p;
 p->name = no_root_file;
 p->file =
 -_-_-

<..cond insert new line..>
 if( !no_root_file ){
   <.end text accent.>
   if( !<.radical-line-off.> ){  put_char(’\n’); }
 }
 -_-_-

<..change ext of root file..>
 if( no_root_file ){
    U_CHAR *name;
    name = m_alloc(char, 256);
    (IGNORED) strcpy((char *)  name, (char *) no_root_file );
    free((void *)  no_root_file);
    no_root_file = name;
    name += (size_t) strlen((char *) name);  while( *(--name) != ’.’ ); name++;
    while( special_n-- ){
        if( (no_root_file+253) == name ) name--;
        *name++ = get_char();
   }
    *name = ’\0’;
 } else {
           U_CHAR str[256], *p;
    p = str;  while( special_n-- ){ *p++ = get_char(); }  *p = ’\0’;
    warn_i_str(43,str);
 }
 -_-_-

<..vars..>+
 static U_CHAR *no_root_file;
 -_-_-

<..name = "tex4htput.html"..>
 bad_arg;
 -_-_-

<..name = derived from input file name..>
 int n = (int) strlen((char *)  job_name );
 name = m_alloc(char, 6 + n);
 (IGNORED) strcpy((char *) name, (char *) job_name);
 n -= 4; *(name + n) = ’\0’;
 (IGNORED) strct(name,".html");
 #ifdef HTM
 name[n+4] =’\0’;
 #endif
 -_-_-

<..name = output file from arg list..>
    int tag = 1;
    int n = (int) strlen( out_name );
 name = m_alloc(char, 6 + n);
 (IGNORED) strcpy((char *) name, out_name);
 while( n-- )   tag = tag && (*(name+n) != ’.’) ;
 if( tag ) (IGNORED) strct(name,".html");
 #ifdef HTM
 name[n+4] = ’\0’;
 #endif
 -_-_-

<..header functions..>+
 static FILE* open_html_file( ARG_I(char*) );
 -_-_-

<..functions..>+
 
 static FILE* open_html_file(name)
      char* name
 ;{   FILE* file;
      char* str;
   str = m_alloc(char, (int) strlen((char *) name) +  1);
   (IGNORED) strcpy((char *) str, (char *) name);
   (IGNORED) printf(" file %s\n", str);
   (IGNORED) fprintf(log_file, "File: %s\n", str);
   if( (file = fopen(str, WRITE_TEXT_FLAGS)) == NULL )  bad_in_file(str);
   free((void *)  str);
   return file;
 }
 -_-_-

<..vars..>+
 static FILE *out_file  = (FILE *) 0,
      *root_file = (FILE *) 0,
      *cur_o_file = (FILE *) 0;
 -_-_-

Close Output

<..close active output filesNO..>
 if( root_file != (FILE *) 0 )  (IGNORED) fclose(root_file);
 -_-_-

Get Input-File Length

Files must have length divisible by four and have 4 to 7 ‘trail’ characters.

Another problem I ran into is that fileno is unavailable to both compiler and linker if I turn on ANSI compilation. I checked where you use it, and it is in only one place, to find the file length of the DVI file. Your code:

{    struct STSTAT temp; 
  (IGNORED) fstat (fileno(dvi_file), &temp); 
  file_len = (long) temp.st_size; 
  if( (file_len % 4) != 0 )  bad_dvi; 
} 

If you change this to use ftell and fseek, you’ll have gained ANSI compatibility (and therewith portability). I tried the following code instead of yours:

<..file-len = size of file..>
 {      long  curr_pos;
   curr_pos = ftell(dvi_file);
   (IGNORED) fseek(dvi_file, 0, SEEK_END);
   file_len = ftell(dvi_file);
   (IGNORED) fseek(dvi_file, curr_pos, <.abs file addr.>);
   if( (file_len % 4) != 0 )  bad_dvi;
 }
 -_-_-

To the best of my nowledge, this works exactly like your code (I tested it). My executable is compiled with this code.

see also fgetpos and fsetpos.

1.7 Coding Hints

[ini (initialization) files in windows]

[detecting tex tree]

[kpathsea]

[more]