diff options
Diffstat (limited to 'Master/texmf-dist/source/generic/tex4ht/tex4ht-t4ht.tex')
-rw-r--r-- | Master/texmf-dist/source/generic/tex4ht/tex4ht-t4ht.tex | 4521 |
1 files changed, 4521 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/generic/tex4ht/tex4ht-t4ht.tex b/Master/texmf-dist/source/generic/tex4ht/tex4ht-t4ht.tex new file mode 100644 index 00000000000..9b534c9490b --- /dev/null +++ b/Master/texmf-dist/source/generic/tex4ht/tex4ht-t4ht.tex @@ -0,0 +1,4521 @@ +% $Id: tex4ht-t4ht.tex 418 2018-07-03 17:37:07Z karl $ +% tex tex4ht-t4ht or ht tex tex4ht-t4ht +% +% Copyright 2009-2018 TeX Users Group +% Copyright 1998-2009 Eitan M. Gurari +% Released under LPPL 1.3c+. +% See tex4ht-cpright.tex for license text. + +% bcc32 -DBCC32 t4ht.c +% gcc -O2 -DKPATHSEA -I/usr/local/teTeX/include -L/usr/local/teTeX/lib -o t4ht t4ht.c -DHAVE_DIRENT_H -lkpathsea + +\input common.tex +\input tex4ht.sty + +\Preamble{xhtml,th4,sections+,xhtml}\EndPreamble + + \input ProTex.sty + \AlProTex{c,<<<>>>,`,title,list,_^,CodeLineNo} + +%\input tex4ht-cpright.tex + +\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.cis.ohio-state.edu/\string~gurari/tpf/} + +\TocAt{Section,SubSection} +\CutAt{Section} + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\LikeChapter{t4ht: postprocessor for tex4ht} + +The compilation of this file requires the packages +\Link[\FTP ProTex.sty]{}{}Pro\TeX\EndLink{} +and \Link[\FTP AlProTex.sty]{}{}AlPro\TeX\EndLink. + +\TableOfContents[Section,SubSection] + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\Section{Outline} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{The Cases} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +The post-processor \`'tex4ht.c' prepares a \`'.lg' file in which it +lists the pictures that need to be generated, and the entries +encountered in \''\Needs{...}'. The \`'.log' file contains the entries +encountered in the \''\Needs-{...}'. The t4ht program (used to be a +Perl script?) treats as commands the entries that are enclosed between +double-quote (\''"') characters, and the other entries as comments. It +first works on the \`'.lg' file and then on the \`'.log' file. +The main output is a new \`'.css'. + + +\<main's body\><<< +`<load env file`> +lg_file = open_file(lg_name,LG_EXT); +if( lg_file ) { + `<mark start lg file`> + `<rewind lg file`> `<stop, if tex4ht.c err`> + `<rewind lg file`> `<CopyTo files`> + `<rewind lg file`> `<htfcss from lg`> + `<rewind lg file`> `<font=(...) from lg`> + `<rewind lg file`> `<identify the empty pictures`> + `<rewind lg file`> `<process gif's`> + `<rewind lg file`> `<process css`> + `<rewind lg file`> `<post-process ext files`> + `<rewind lg file`> `<post-process files`> + `<rewind lg file`> `<mv lg/File to dir and chmod`> + `<rewind lg file`> `<process user commands`> + (IGNORED) fclose(lg_file); +} +>>> + +\<mv lg/File to dir and chmod\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("File: ", TRUE, lg_file); + status = scan_until_end_str("", 1, status, lg_file); + status = status && !eq_str(match[1],tmp_name); + if( status ){ + FILE* file; + file = fopen(match[1], READ_TEXT_FLAGS); + if( file ){ + (IGNORED) fclose(file); + } else { status = FALSE; } + } + if( status ){ + if( dir ){ + (void) execute_script(copy_script, match[1], + dir? dir :"",".",""); + } + if( ch_mod ){ + (void) execute_script(chmod_script, ch_mod, + dir? dir:"",match[1], ""); + } +} } +>>> + +% Need to input tex4ht-cpright.tex at this point, +% if not, it causes an error while expanding the +% macros like `jobname.tex, `version, ... +% Still greek to me. :( CVR/2010/02/11 +% +\input tex4ht-cpright.tex + + +\<t4ht.c\><<< +/* t4ht.c (`version), generated from `jobname.tex + Copyright (C) 2009-2018 TeX Users Group + Copyright (C) `CopyYear.1998. Eitan M. Gurari +`<TeX4ht copyright`> +*/ +`<t4ht.h`> +`<defines`> +`<vars`> +`<header functions`> +`<functions`> +`[ +int `<CDECL`> main(argc, argv) + int argc`; + Q_CHAR **argv +;{ `<main's vars`> + `<resplit argv for windows`> + `<set signals`> + `<program signature`> + `<main's init`> + + `<scan job args`> + `<main's body`> + return 0; +} +>>> + + +\<program signature\><<< +(IGNORED) printf("----------------------------\n"); +#ifndef KPATHSEA +#ifdef PLATFORM + (IGNORED) printf("t4ht.c (`version %s)\n",PLATFORM); +#else + (IGNORED) printf("t4ht.c (`version)\n"); +#endif +#else +#ifdef PLATFORM + (IGNORED) printf("t4ht.c (`version %s kpathsea)\n",PLATFORM); +#else + (IGNORED) printf("t4ht.c (`version kpathsea)\n"); +#endif +#endif + +`<handle quoted arguments`> +{ int i; + for(i=0; i<argc; i++){ + (IGNORED) printf("%s%s ", (i>1)?"\n " : "", argv[i]); } + (IGNORED) printf("\n"); +} +>>> + + + +\SubSection{char, signed char, unsigned char (gcc man)}: + + + Each kind of machine has a default for what char should + be. It is either like unsigned char by default or like + signed char by default. + + Ideally, a portable program should always use signed + char or unsigned char when it depends on the signedness + of an object. But many programs have been written to + use plain char and expect it to be signed, or expect it + to be unsigned, depending on the machines they were + written for. This option, and its inverse, let you + make such a program work with the opposite default. + + The type char is always a distinct type from each of + signed char and unsigned char, even though its behavior + is always just like one of those two. + + + + +\<definesNO\><<< +#define Q_CHAR signed char +#define U_CHAR unsigned char +#define C_CHAR char +#define Q_NULL (Q_CHAR *) 0 +#define U_NULL (U_CHAR *) 0 +#define C_NULL (C_CHAR *) 0 +>>> + +Pointers to strings must use \`'C_CHAR', since we don't +know how string constants are treated there. + + +\<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 +>>> + +\SubSection{EOF Character} + + +\<vars\><<< +static int eoln_ch; +>>> + +\Verbatim +OBTW: when compiling t4ht.c, I get messages about the uselessness of comparing +chars (which are unsigned, at least on a IRIX 6.5) to EOF which is defined as +-1 in stdio.h).... and indeed it program loops endlessly. +Adding the lines + #undef EOF + #define EOF 255 +after the last #include gets the effect that you probably want (or perhaps +better would be to define a constant EOFCHAR or something.) +\EndVerbatim + +The getc returns the next character as an unsigned char converted to int. +This is so to allow all characters to be return as well as end-of-file +indicators (-1 in stdio) and error indicator. + + + + +%%%%%%%%%%%%% +\Section{Stop on tex4ht.c Err} +%%%%%%%%%%%%% + + + +\<stop, if tex4ht.c err\><<< +if( check_tex4ht_c_err ){ + eoln_ch = (int) 'x'; + while( eoln_ch != EOF ) { + status = scan_str("tex4ht.c error: ", TRUE, lg_file); + if( status ){ + (IGNORED) fprintf(stderr, + "--- Error --- tex4ht.c ran into problems\n" + ); + exit(EXIT_FAILURE); + } + status = scan_until_end_str("", 1, status, lg_file); +} } +>>> + + + + +\<vars\><<< +static BOOL check_tex4ht_c_err = FALSE; +>>> + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\Section{Platform-dependent Code} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + + + + + + + + + + + + + + + + + + + +\SubSection{PreProcessor Directives} + + +Symantec C++ for wid95: +\''sc t4ht.c -mn -o+time -WA -3 -a8 -c -D_CONSOLE=1 -ot4ht.obj' + + +\<defines\><<< +#define IGNORED void +>>> + + + +\<t4ht.h\><<< +/* ********************************************** + Compiler options * + (uncommented | command line) * +------------------------------------------------* + 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 SYSTEM_FUNCTION_OK +#define CDECL .......... +#define BCC32 bordland c++ + +************************************************* + Tex4ht variables * + (uncommented | command line) * +----------------------------------------------- */ +`<h-defines`> +/* ******************************************** */ +`<define MSVC-1-52`> +`<bordland: bcc32 -DBCC32 t4ht`> +`<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`> +>>> + + +\<bordland: bcc32 -DBCC32 t4ht\><<< +#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\><<< +#ifdef KPATHSEA +#include <kpathsea/config.h> +#endif +#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. + + + +\<defines\><<< +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif +>>> + +\<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. + + + + +\<t4ht.h\><<< +#ifdef DOS +#define PROTOTYP +#endif +#ifdef ANSI +#define PROTOTYP +#endif +#ifdef KWIN32 +#define PROTOTYP +#endif +>>> + +\<defines\><<< +#ifdef PROTOTYP +#define MYVOID 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 MYVOID +#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 +>>> + + + + + +\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/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 */`% +`<h-include after KPATHSEA`> +>>> + +\<h-defines 2\><<< +`<h-include before KPATHSEA`> +#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 */`% +`<h-include after KPATHSEA`> +>>> + + +The \`'__cdecl' is defined in KPATHSEA: kpathsea/c-protos.h +is defined to nothing for compilers +other than MS. + +\<t4ht.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 +>>> + + + + + +\SubSection{Compilers} + + +\List{} +\item {BCC32} + +For Win 95. + +Options (\''bcc32' comamnd): + +\Verbatim +Borland C++ 5.0 for Win32 Copyright (c) 1993, 1996 Borland International +Syntax is: BCC32 [ options ] file[s] * = default; -x- = turn switch x off + -3 * 80386 Instructions -4 80486 Instructions + -Ax Disable extensions -B Compile via assembly + -C Allow nested comments -Dxxx Define macro + -Exxx Alternate Assembler name -Hxxx Use pre-compiled headers + -Ixxx Include files directory -K Default char is unsigned + -Lxxx Libraries directory -M Generate link map + -N Check stack overflow -Ox Optimizations + -P Force C++ compile -R Produce browser info + -RT * Generate RTTI -S Produce assembly output + -Txxx Set assembler option -Uxxx Undefine macro + -Vx Virtual table control -X Suppress autodep. output + -aN Align on N bytes -b * Treat enums as integers + -c Compile only -d Merge duplicate strings + -exxx Executable file name -fxx Floating point options + -gN Stop after N warnings -iN Max. identifier length + -jN Stop after N errors -k * Standard stack frame + -lx Set linker option -nxxx Output file directory + -oxxx Object file name -p Pascal calls + -tWxxx Create Windows app -u * Underscores on externs + -v Source level debugging -wxxx Warning control + -xxxx Exception handling -y Produce line number info + -zxxx Set segment names +\EndVerbatim + + +\item {BCC} + +For DOS. + +\item {MSVC++} + +For DOS. + +\`'c:\msvc\bin\cl -Ic:\msvc\include -DDOS t4ht.c' + +In tex-live \`' cl -D_X86_=1 -DWINVER=0x0400 -DWIN32 -D_WIN32 +-DWIN32_LEAN_AND_MEAN -D_MT -D_DLL -DKPATHSEA +-D_IMPORT -DANSI -I. -I. -I.. -IG:\fptex\source\web2c-7.2 -c -W3 +-DCRTAPI1=_cdecl -DCRTAPI2=_cdecl -nologo -O2x -G5rs -Gy +-c /Fodynamic\t4ht.obj .\t4ht.c' + +The following are the available flags (\''c:\msvc\bin\cl -help'). + +\Verbatim + C COMPILER OPTIONS + + -MEMORY MODEL- +/AS small model (default) /AC compact model +/AM medium model /AL large model +/AH huge model /AT tiny model (.COM files) +/A<string> (custom memory model) + -OPTIMIZATION- +/O enable optimization (same as /Ot) /O1 minimize space +/O2 maximize speed /Oa assume no aliasing +/Ob<n> inline expansion (default n=0) /Oc local common subexpression opt. +/Od disable optimization (default) /Oe enable registers allocation +/Of[-] toggle p-code quoting /Og global common subexpression opt. +/Oi enable intrinsic functions /Ol enable loop optimizations +/On disable ``unsafe'' optimizations /Oo[-] toggle post code-gen. opt. +/Op[-] improve floating-pt consistency /Oq enable maximum p-code optimization +/Or gen. common exit code (CodeView) /Os favor code size +/Ot favor code speed /Ov[-] toggle p-code frame sorting +/OV<n> control inlining by func. size /Ow assume cross-function aliasing +/Ox maximum opts. (/Ob1cegilnot /Gs) /Oz enable ``unsafe'' optimizations + -CODE GENERATION- +/G0 8086 instructions (default) /G1 186 instructions +/G2 286 instructions /G3 386 instructions + (press <return> to continue) +/GA protected-mode Win entry/exit code /GD protected-mode Win entry/exit code +/GE<x> customize Windows entry/exit /Gq backwards compatibility with v. 6 +/Gc Pascal style calling conventions /Gd C style calling conventions +/Ge use stack-check calls /Gf enable string pooling +/Ge use stack-check calls /Gf enable string pooling +/Gs remove stack-check calls /Gn remove p-code native entry points +/Gp<num> specify p-code entry tables /Gr _fastcall style calling convention +/Gt[num] data size threshold /GW real-mode Windows entry/exit code +/Gw real-mode Windows entry/exit code /Gx assume that data is near +/Gx- assume that data is far /Gy separate functions for linker +/Zr check null pointers (/f only) + -OUTPUT FILES- +/Fa[file] name assembly listing file /Fc[file] name source/object listing +/Fd[file] name .PDB filename /Fe<file> name executable filename +/Fl[file] name object listing filename /Fm[file] name map filename +/Fo<file> name object filename /Fr[file] name .SBR filename +/Fp<file> name .PCH filename /FR[file] name extended .SBR filename +/Fs[file] name source listing filename + -PREPROCESSOR- +/C don't strip comments /D<name>[=|#text] define macro +/E preprocess to stdout /EP same as /E but no #line +/I<directory> add #include path /P preprocess to file +/U<name> remove predefined macro /u remove all defined macros + (press <return> to continue) +/X ignore "standard places" + -LANGUAGE- +/vd{0|1} disable/enable vtordisp /vm<x> type of pointers to members +/Z7 C 7 style CodeView information /Za disable extensions (implies /Op) +/Zd line number information /Ze enable extensions (default) +/Zg generate function prototypes /Zi prepare for debugging (CodeView) +/Zl omit default library name in .OBJ /Zp[n] pack structs on n-byte boundary +/Zs check syntax only + -FLOATING POINT- +/FPa calls with altmath /FPc calls with emulator +/FPc87 calls with 8087 library /FPi inline with emulator (default) +/FPi87 inline with 8087 + -SOURCE LISTING- +/Sl<columns> set line width /Sp<lines> set page length +/St<string> set title string /Ss<string> set subtitle string + -MISCELLANEOUS- +/batch specify batch mode compilation /Bm<num> set compiler's available mem. +/c compile only, no link /H<num> external name length +/J default char type is unsigned /f select fast compiler (default) +/f- select optimizing compiler /Yc create .PCH file +/Yd put debug info in .PCH file /Yu use .PCH file +/YX automatic precompiled header /nologo suppress copyright message + (press <return> to continue) +/Mq compile for QuickWin /ND<name> name data segment +/NM<name> name code segment /NQ<name> combine p-code temp segments +/NT<name> name code segment /NV<name> name far v-table segment +/Tc<file> compile file without .c /Tp<file> compile file without .cpp +/V<string> set version string /W<n> warning level (default n=1) +/w disable all warnings /WX treat all warnings as errors +/Zn turn off SBRPACK for .SBR files + -MASM SUPPORT- +/MA<MASM switch> /Ta<file> assemble file without .asm + -LINKING- +/F <hex_num> stack size (hex. bytes) /Lr append 'r' to default lib in .OBJ +/link [lib] give lib name to linker /Ln do not link CRT.LIB +/Ld select dynamically-linked library /Lw select statically-linked library +\EndVerbatim + + +\EndList + +\SubSection{DJGPP} + + + + +\Verbatim + + * tex4ht.c [__DJGPP__] (ANSI, DOS_GIF_FILE): Define. + (WRITE_BIN_FLAGS, READ_BIN_FLAGS): Use binary mode with DJGPP. + (dos_file_names): New variable. + (sig_err): If got fatal signal other than SIGINT or SIGQUIT, don't + return to caller, since the program will be aborted otherwise. + (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. +\EndVerbatim + + + +\<DJGPP\><<< +#ifdef __DJGPP__ +#define DOS_WIN32 +#define ANSI +#endif +>>> + + + + +\<DJGPP signals\><<< +#ifdef __DJGPP__ + if (s != SIGINT && s != SIGQUIT) + exit(EXIT_FAILURE); +#endif +>>> + + + + +\SubSection{Slashes n Directory Pathes} + + + + +\<defines\><<< +#if defined(DOS_WIN32) || defined(__DJGPP__) +#define dir_path_slash(str) (is_forward_slash(str)? '/' : '\\') +#else +#define dir_path_slash(str) '/' +#endif +>>> + + + +\<header functions\><<< +#if defined(DOS_WIN32) || defined(__DJGPP__) + static BOOL is_forward_slash( ARG_I(Q_CHAR *) ); +#endif +>>> + +\<functions\><<< +#if defined(DOS_WIN32) || defined(__DJGPP__) +`[ +static BOOL is_forward_slash(str) + Q_CHAR * str +;{ + while( *str ){ if( *(str++) == '/' ) { return TRUE; } } + return FALSE; +} +#endif +>>> + + + + + + + + +\Section{Command-Line Options} + + +\SubSection{Available Options} + +\List{disc} +\item \`'.../'---Directory where files should be sent +\item \`'-mXXX'---\`'chmod XXX' for files +\item \`'-e...'---Name of invisible gif +\item \`'-d'---Directory for config files +\item \`'-p'---Ignore pictures (but not pictorial symbols) +\item \`'-i'---Debugging info +\item Other---Name of dvi file +\EndList + + +\Verbatim + dvips -mode ibmvga -D 110 -f foo.idv -pp 92 > tmp.ps + convert -crop 0x0 -density 110x110 -transparent '#FFFFFF' tmp.ps foo.gif + mv foo.gif /WWW/temp/. + cp foo.html /WWW/temp/. + chmod 644 /WWW/temp/foo.* +\EndVerbatim + + +\<command line options\><<< +"\n--------------------------------------------------------------------\n" +"t4ht [-f<dir char>]filename ...\n" +" -b ignore -d -m -M for bitmaps\n" +" -c... choose named segment in env file\n" +" -d... directory for output files (default: current)\n" +" -e... location of tex4ht.env\n" +" -i debugging info\n" +" -g ignore errors in system calls\n" +" -m... chmod ... of new output files (reused bitmaps excluded)\n" +" -p don't convert pictures (default: convert)\n" +" -r replace bitmaps of all glyphs (default: reuse old ones)\n" +" -M... chmod ... of all output files\n" +" -Q quit, if tex4ht.c had problems\n" +" -S... permission for system calls: *-always, filter\n" +" -X... content for field %%3 in X scripts\n" +" -.... content for field %%2 in . scripts\n\n" +"Example: \n" +" t4ht name -d/WWW/temp/ -etex4ht-32.env -m644\n" +"--------------------------------------------------------------------\n" +>>> + + +If option \`'-e' is present, empty pictures are replaced +with the named file (e.g., \`'empty.gif'). + + + + + +\SubSection{Scanning the Options} + + + + +\<vars\><<< +static Q_CHAR *ch_mod = Q_NULL; +static Q_CHAR *debug = Q_NULL; +static Q_CHAR *Xfield = Q_NULL; +static Q_CHAR *Dotfield = Q_NULL; +static Q_CHAR *dir = Q_NULL; +static Q_CHAR *lg_name = Q_NULL, tmp_name[255], job_name[255]; +static Q_CHAR *nopict = Q_NULL; +static Q_CHAR *bitmaps_no_dm = Q_NULL; +static BOOL newchmod = FALSE; +static Q_CHAR *noreuse = Q_NULL; +>>> + + +\<scan job args\><<< +{ int i; + Q_CHAR *p, *q; + `<kpathsea arg 0`> + `<default args`> + if( argc == 1 ){ bad_arg; } + for(i=1; i<argc; i++){ + if( *( p=argv[i] ) == '-' ){ `<scan flaged args`> } + else + { lg_name = argv[i]; } + } + if( lg_name == NULL ){ bad_arg; } + `<set tmp file name`> + `<set job file name`> +} +>>> + + +\<handle quoted arguments\><<< +{ int i, count = 0; + for(i=0; i<argc; i++){ + Q_CHAR *p = argv[i]; + count++; + if( (*p == '\'') || (*p == '\"') ){ + int cnt; + int len = 0; + for( cnt=i; cnt < argc; cnt++ ){ + len += (int) strlen((char *) argv[cnt]); + if( *(argv[cnt] + (int) strlen((char *) argv[cnt]) -1) == *p ){ + Q_CHAR * arg = m_alloc(char, len + cnt - i + 1); + Q_CHAR * toArg = arg; + Q_CHAR *pp; + i--; + do { + pp = argv[++i]; + while( *pp != '\0' ){ + if( *pp != *p ){ *(toArg++) = *pp; } + pp++; + } + *(toArg++) = ' '; + } while ( i != cnt ); + *(toArg-1) = '\0'; + argv[count-1] = arg; + break; + } } } } + argc = count; +} +>>> + + + + +\<set tmp file name\><<< +{ Q_CHAR *p, *q; + FILE* file; + (IGNORED) strcpy((char *) (char *) tmp_name, (char *) (char *) lg_name); + p = q = tmp_name + strlen((char *) tmp_name ); + while( p != tmp_name ){ + if( *p == '.' ){ + if( eq_str( p+1,LG_EXT ) ) { *p = '\0'; } + else { + (IGNORED) strct( tmp_name, LG_EXT); + file = fopen( tmp_name, READ_TEXT_FLAGS ); + if( file ){ + (IGNORED) fclose(file); *q = '\0'; + } else { *p = '\0'; } + } + break; + } + p--; + } + (IGNORED) strct(tmp_name, ".tmp"); +} +>>> + + +\<set job file name\><<< +(IGNORED) strcpy((char *) job_name, (char *) tmp_name); +*(job_name + strlen((char *) job_name) - 4) = '\0'; +>>> + + + +\Verbatim +I found that I couldn't compile t4ht.c with KPATHSEA defined, and then noticed +that it doesn't include any of the kpathsea headers. So I have patched t4ht.c +to create two versions: one with the necessary kpathsea headers and one +without. This is the output produced by 'diff'. Let me know if you want to +merge my changes into your t4ht.c, and/or if you notice any errors! I have +changed the second argument of 'kpse_set_program_name' from NULL (which would +effectively mean argv[0]) to 'tex4ht', as that saves having to add a +'T4HTINPUTS' (or 'T4HTKINPUTS') variable into the kpathsea configuration file +'texmf.cnf' pointing to the same place for 'tex4ht.env' as the 'TEX4HTINPUTS' +variable. + +For t4ht.c, the kpathsea library is only useful for locating the tex4ht.env +configuration file. But as it can be used for this purpose for tex4ht.c, it +seems a pity not to enable it for its companion program too. + +> 94a99,102 +> > #ifdef KPATHSEA +> > #include <kpathsea/progname.h> +> > #include <kpathsea/tex-file.h> +> > #endif +> 943c951 +> < kpse_set_program_name (argv[0], NULL); +> --- +> > kpse_set_program_name (argv[0], "tex4ht"); +\EndVerbatim + +\<kpathsea arg 0\><<< +#ifdef KPATHSEA + kpse_set_program_name (argv[0], "tex4ht"); +#endif +>>> + + + +If \`'strlen((char *) 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( `<not a single char option?`> ) + { if( ++i == argc ) bad_arg; } + q = argv[i]; +} else q = p+2; +switch( *(p+1) ){ + case 'M':{ ch_mod = q; newchmod = TRUE; break; } + case 'S':{ `<permission for system calls`> break; } + case 'X':{ Xfield = q; break;} + case 'b':{ bitmaps_no_dm = q-1; break;} + case 'c':{ `<env blocks selector`> break;} + case 'd':{ dir = (*q=='~')? abs_addr(q,NULL) : q; break; } + case 'e':{ `<get .env directory from com ln`> break; } + case 'f':{ `<get file name wo dir`> break; } + case 'i':{ debug = q-1; break;} + case 'g':{ always_call_sys = TRUE; break;} + case 'm':{ ch_mod = q; break; } + case 'p':{ nopict = q-1; break;} + case 'Q':{ check_tex4ht_c_err = TRUE; break;} + case 'r':{ noreuse = q-1; break;} + case '.':{ Dotfield = q; break;} + default:{ bad_arg; } +} +>>> + + +\<not a single char option?\><<< + (*(p+1) != 'i') +&& (*(p+1) != 'p') +&& (*(p+1) != 'r') +&& (*(p+1) != 'b') +&& (*(p+1) != 'g') +&& (*(p+1) != 'Q') +>>> + + + +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. + + +\<get file name wo dir\><<< +p = p + 2; +lg_name = p + (int) strlen((char *) p ); +while( *lg_name != *p ){ lg_name--; } +lg_name++; +>>> + + + + + +\<header functions\><<< +static char * abs_addr( ARG_II( U_CHAR *, U_CHAR *) ); +>>> + +\<functions\><<< +`[ +static char * abs_addr( dir, base) + U_CHAR *dir`; + U_CHAR *base + +;{ U_CHAR *p; + p = m_alloc(char, (int) strlen((char *) dir ) + + (base? (int) strlen((char *) base ):0) + + (int) strlen((char *) HOME_DIR )); + *p = '\0'; + if( (*(dir+1) == '~') && base ){ + if( *base == '~' ){ + (IGNORED) strct(p, HOME_DIR); + (IGNORED) strct(p, base+1); + } else { + (IGNORED) strct(p, base); + } + (IGNORED) strct(p, dir+2); + } else { + (IGNORED) strct(p, HOME_DIR); + (IGNORED) strct(p, dir+1); + } + return p; +} +>>> + +\<vars\><<< +U_CHAR *HOME_DIR; +>>> + +\<main's init\><<< +HOME_DIR = getenv("HOME"); +>>> + + + + +\Section{Identify the Empty Pictures} + + +Messages about figures that don't exist are treated as requests for +empty figures. Typically, they shouldn't be present unless they are +programmed into \''\setbox'-like commands. tex4ht-c identifies in the +\''.lg' file the empty figures it finds. + +The messages in the ``.lg'' file look like +\`'--- empty picture --- aa.idv[1] ---'. + + + +\<identify the empty pictures\><<< +{ struct empty_pic_struct *last; + last = empty_pic = (struct empty_pic_struct *) 0; + while( TRUE ) { + status = scan_str("--- empty picture --- ", TRUE, lg_file); + status = scan_until_str( ".idv[" , 1, status, lg_file); + status = scan_until_end_str("] ---", 1, status, lg_file); + if( status ){ `<add empty pic`> } + if ( eoln_ch == EOF ){ break; } + } + `<add empty pic`> + last->next = (struct empty_pic_struct *) 0; + last->n = 100000; +} +>>> + + +\<add empty pic\><<< +if( last == (struct empty_pic_struct *) 0 ){ + last = empty_pic = (struct empty_pic_struct *) + m_alloc(struct empty_pic_struct, (int) 1); +} else { + last = last->next = (struct empty_pic_struct *) + m_alloc(struct empty_pic_struct, (int) 1); +} +last->next = (struct empty_pic_struct *) 0; +last->n = get_long_int(match[1]); +>>> + + +\<main's vars\><<< +struct empty_pic_struct *empty_pic; +>>> + +\<defines\><<< +struct empty_pic_struct{ + long int n; + struct empty_pic_struct *next; +}; +>>> + + + +The list of empty pictures is stored in \`'emptypic'. + +%%%%%%%%%%%%%%%%%%%%%%% +\Section{Process Gifs} +%%%%%%%%%%%%%%%%%%%%%%% + + + +%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{The Scripts} +%%%%%%%%%%%%%%%%%%%%%%% + +\<script for dvigif\><<< +if( debug ){ (IGNORED) printf(".......'G' script\n"); } +dvigif_script = add_script(dvigif_script); +>>> + + +\Verbatim +--- needs --- aa.idv[80] ==> aa79x.gif --- +--- characters --- +--- needs --- aa.idv[81] ==> foo.gif --- +\EndVerbatim + + +\<process gif's\><<< +{ BOOL characters, skip; + characters = skip = FALSE; + while( TRUE ) { + status = scan_until_str("--- ", 1, TRUE, lg_file); + status = scan_until_str( " ---" , 2, status, lg_file); + if( status ) { + if( eq_str(match[1],"--- ") ){ + if( eq_str(match[2],"needs ---") ){ + `<--- needs ---...`> + } else if( eq_str(match[2],"characters ---") ){ + `<--- characters ---...`> + } else { `<--- ??? ---...`> } + } else { `<???--- needs ---...`> } + } + if ( eoln_ch == EOF ){ break; } +} } +>>> + + +\<--- ??? ---...\><<< +status = scan_until_end_str("", 1, status, lg_file); +>>> + +\<???--- ??? ---...\><<< +status = scan_until_end_str("", 1, status, lg_file); +>>> + + +\<--- characters ---...\><<< +status = scan_until_end_str("", 1, status, lg_file); +characters = eq_str(match[1],""); +>>> + + +\SubSection{Identifying the requests} + + + +\<--- needs ---...\><<< +status = scan_until_str(" ", 1, status, lg_file); +status = scan_until_str(".idv", 1, status, lg_file); +status = scan_until_str("[", 2, status, lg_file); +status = scan_until_str("] ==> ", 2, status, lg_file); +status = scan_until_str(" ", 3, status, lg_file); + *(match[3] + (int) strlen((char *) match[3]) - 1) = '\0'; +status = scan_until_end_str("---", 4, status, lg_file); +if( status ) { + `<dvi2gif vars`> + long int gif_i; + Q_CHAR *p; + gif_i = get_long_int(match[2]); + p = match[2]; + *(p + (int) strlen((char *) p) - 6) = '\0'; + if( characters ){ + `<translate symbol gifs`> + } else { `<translate non-symbol gifs`> } +} +>>> + + +\SubSection{General Pictures} + + +\`'--- needs --- aa.idv[80] ==> aa79x.gif ---' + +\<translate non-symbol gifs\><<< +if( gif_i == `<empty picture`> ) { + `<insert empty picture`> +} else { `<insert non-empty picture`> } +>>> + + +\<insert non-empty picture\><<< +if( !nopict && !skip ){ + `<dvi into gif`> +} +>>> + + +\<insert empty picture\><<< +if( !skip ){ + (void) execute_script(empty_fig_script, + (dir && !bitmaps_no_dm )? dir :"", match[3],"",""); + if( ch_mod && !bitmaps_no_dm && !system_return ){ + (void) execute_script(chmod_script, ch_mod, + dir?dir:"",match[3], ""); + } +} +empty_pic = empty_pic->next; +>>> + + + +\<empty picture\><<< +empty_pic->n +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Pictorial Symbols} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\<translate symbol gifs\><<< + Q_CHAR filename[255]; + FILE* file; +(IGNORED) strcpy((char *) filename, ""); +if( dir && !bitmaps_no_dm ){ (IGNORED) strct(filename, dir); } +(IGNORED) strct(filename, match[3]); +file = fopen(filename, READ_TEXT_FLAGS); +if( !file || noreuse ){ + `<dvi symbols into gif`> +} else { + (IGNORED) fclose(file); + if( newchmod ) + { `<chmod for glyphs`> } + (IGNORED) printf("%s already in %s\n", match[3], + dir? dir : "current directory" ); +} +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{The Conversion Code} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\<dvi into gif\><<< +filtered_dvigif_script = filterGifScript(dvigif_script, match[3]); +(void) execute_script( + filtered_dvigif_script,match[1],match[2],match[3],job_name); +(void) free_script( filtered_dvigif_script ); +if( dir && !bitmaps_no_dm && !system_return ){ + (void) execute_script(move_script,match[3],dir,".",""); +} +if( ch_mod && !bitmaps_no_dm && !system_return ){ + (void) execute_script(chmod_script, ch_mod, dir?dir:"",match[3], ""); +} +>>> + +\<dvi symbols into gif\><<< +filtered_dvigif_script = dvigif_glyp_script? + filterGifScript(dvigif_glyp_script, match[3]): + filterGifScript(dvigif_script, match[3]); +(void) execute_script( + filtered_dvigif_script,match[1],match[2],match[3],job_name); +(void) free_script( filtered_dvigif_script ); +if( dir && !bitmaps_no_dm && !system_return ){ + (void) execute_script(move_script,match[3],dir,".",""); +`<chmod for glyphs`> +} +>>> + + +\<chmod for glyphs\><<< +if( ch_mod && !bitmaps_no_dm && !system_return ){ + (void) execute_script(chmod_script, ch_mod, dir?dir:"",match[3], ""); +} +>>> + + +\<dvi2gif vars\><<< +struct script_struct + * filtered_dvigif_script = NULL_SCRIPT; +>>> + + + + + + + + + + + + + + + + + + + + + + +\<header functions\><<< +static void execute_script( + ARG_V(struct script_struct*,const Q_CHAR *,const Q_CHAR *,const Q_CHAR *,const Q_CHAR *) ); +>>> + +\<functions\><<< +`[ +static void execute_script(script,match_1,match_2,match_3,match_4) + struct script_struct* script`; + const Q_CHAR * match_1`; + const Q_CHAR * match_2`; + const Q_CHAR * match_3`; + const Q_CHAR * match_4 + +;{ struct script_struct* temp; + Q_CHAR *p, *q; + const Q_CHAR *t; + `<texmf := ...`> + temp = script; system_return = 0; + while( temp ){ + `<command = temp-command`> + if( (command[0] != '\0') && !system_return ){ + `<execute system command`> } + temp = temp->next; +} } +>>> + + +We went to \`'%%%', \`'%%1', ... instead of \`'%%', \`'%1', ... +to accomodate some needds of dos. Example (yet, where exactly the +conflict is?): + +\Verbatim +if exist %1.dvi goto yes_dvi +goto end +yes_dvi: +DEL tmp.ps +call dvips32 -f %1 -p %2 -l %2 -o tmp.ps -mode ibmvga -D 110 +DEL %3 +call convert -crop 0x0 -density 110x110 -transparent '#FFFFFF' tmp.ps %3 +end: +\EndVerbatim + + + +\<command = temp-command\><<< +p = temp->command; +q = command; +while( *p != '\0' ){ + *q = *(p++); + if( (*q == '%') && (*p == '%') + && ( (*(p+1) == '%') + || (*(p+1) == '~') + || ( (*(p+1) >= '0') && (*(p+1) < '5') ) ) + ){ p++; + switch( *(p++) ){ + case '%':{ q++; break; } + case '0':{ t = job_name; + while( *t != '\0' ){ *(q++) = *(t++); } break; } + case '1':{ t = match_1; + while( *t != '\0' ){ *(q++) = *(t++); } break; } + case '2':{ t = match_2; + while( *t != '\0' ){ *(q++) = *(t++); } break; } + case '3':{ t = match_3; + while( *t != '\0' ){ *(q++) = *(t++); } break; } + case '4':{ t = match_4; + while( *t != '\0' ){ *(q++) = *(t++); } break; } + case '~':{ `<q += texmf path`> break; } + default: { } + }} else { q++; } +} +*q = '\0'; +>>> + +The argument `\Verb=%%~=' is replaced with the value of +\Verb=${TEXMFDIST}= under Kpathsea. If such a value +is not available, the character `\Verb=~=' is used. The variable +offers the parent directory of where tex4ht resides, e.g., +\Verb=/usr/local/texlive/2018/texmf-dist=. We use TEXMFDIST in +preference to SELFAUTOPARENT (as was done until June 2018), or +TEXMFROOT, because in practice it works on both \TeX\ Live and MiK\TeX, +while the others do not. + +\<texmf := ...\><<< +#ifdef KPATHSEA +const char * texmf = kpse_var_value( "TEXMFDIST" ); +#endif +>>> + +\<q += texmf path\><<< +#ifdef KPATHSEA + if( texmf ){ + t = texmf; + while( *t != '\0' ){ *(q++) = *(t++); } + } else { + *(q++) = '~'; + } +#else + *(q++) = '~'; +#endif +>>> + + + + +\Verbatim + +> > help tinkering with the code. If you'll have a chance at some +> > point to pass on the kind of changes you are doing, I'll be interested +> > to hardwire them in the code as compile/run-time options. +> for instance, I add -Pem to the dvips command line to access the EM +> fonts instead of EC (faster) +> +> i also change the name of "convert.exe" to "iconvert.exe" because it +> conflicts with a native NT utility to convert file systems :-} + +\EndVerbatim + +\Verbatim +dvips -mode $mf -D $density -f $_[0] -pp $_[1] > tmp.ps +\EndVerbatim + +\<defines\><<< +#ifndef HTFDIR +#define HTFDIR "" +#endif +>>> + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Filter} +%%%%%%%%%%%%%%%%%%%%%%%% + + + +Three cases for `G' and `F' scripts. + +\List{} +\item +{The first record doesn't start with a period} +Use the script until its end or a period command +\item +{The first record starts with a period without an extension} +Use the script until its end or a period command +\item +{The first record starts with a period with an extension} +Use the script until its end or a period command, if the extension +fits the output figure. + +\EndList + + +\<header functions\><<< +static struct script_struct * filterGifScript( + ARG_II( struct script_struct *, Q_CHAR *) ); +>>> + +\<functions\><<< +`[ +static struct script_struct * filterGifScript( script, file) + struct script_struct *script`; + Q_CHAR *file +;{ + struct script_struct *filtered_script, *scr, + *old_script, + *new_script; + Q_CHAR *command, *ext; + filtered_script = NULL_SCRIPT; + if( script == NULL_SCRIPT ) + return filtered_script; + old_script = script; + command = old_script->command; + if( *command != '.' ){ + `<script until dot`> + } else { + `<script from dot`> + } +} +>>> + +\<script until dot\><<< +new_script = NULL_SCRIPT; +while( old_script != NULL_SCRIPT ){ + command = old_script->command; + if( *command == '.' ){ return filtered_script; } + scr = (struct script_struct *) + m_alloc(struct script_struct, (int) 1); + scr->command = old_script->command; + scr->next = NULL_SCRIPT; + if( new_script == NULL_SCRIPT ){ + filtered_script = new_script = scr; + } else { + new_script = new_script->next = scr; + } + old_script = old_script->next; +} +return filtered_script; +>>> + +\<script from dot\><<< +`<ext = file ext`> +while( TRUE ){ + if( old_script == NULL_SCRIPT ){ + return NULL_SCRIPT; + } + command = old_script->command; + if(*command != '.') { + old_script = old_script->next; + continue; + } + old_script = old_script->next; + if( (*(command+1) == '\0') || eq_str(ext,command) ){ + break; + } +} +`<script until dot`> +>>> + + +\<ext = file ext\><<< +ext = file; +while( *ext != '\0' ){ ext++; } +while( (*ext != '.') && (ext != file) ){ ext--; } +>>> + + +\<header functions\><<< +void free_script( + ARG_I( struct script_struct *) ); +>>> + +\<functions\><<< +`[ +void free_script(script) + struct script_struct *script +;{ + struct script_struct *temp; + while( script != NULL_SCRIPT ){ + temp = script; + script = script->next; + free( temp ); + } +} +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Ignore/Noignore Commands} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\<???--- ??? ---...\><<< +status = scan_until_end_str("", 1, status, lg_file); +>>> + + +\Verbatim +l. 10 --- needs --- ignore --- +l. 11 --- needs --- end ignore --- +\EndVerbatim + + +We didn't check below the \`'l. dddd ' part. + +\<???--- needs ---...\><<< +status = scan_until_end_str(" ignore ---", 2, status, lg_file); +if( status ){ + skip = eq_str(match[2]," ignore ---") ? TRUE : + ( eq_str(match[2]," end ignore ---") ? FALSE : skip ); +} +>>> + + + +%%%%%%%%%%%%%%%%%%%%%%% +\Section{CopyTo files} +%%%%%%%%%%%%%%%%%%%%%%% + + +There are 6 supporting dvi variations of the +`CopyTo to-file op group' + dvi command: + +\List{} +\item{From} Start copying (at current address) +\item{Until} End copying (at current address) +\item{Skip} Start skipping (from current address) +\item{Cont} End skipping (at current-address) +\item{Addr integer-label} Associate current + address with the integer-label of the given group +\item{Set integer-label} + Replace the `current address' in the following Skip/Cont (and + From/Until ?) commands with the address associated to the + integer-label of the given group by an Addr command +\EndList + +The code +\Verbatim +B0 + \ht:special {t4ht@DCopyTo: \jobname-js.tex From bib } +B1 + \ht:special {t4ht@DCopyTo: \jobname-js.tex Skip bib } +B2 + \ht:special {t4ht@DCopyTo: \jobname-js.tex Addr1 bib } +B3 + \ht:special {t4ht@DCopyTo: \jobname-js.tex Addr2 bib } +B4 + \ht:special {t4ht@DCopyTo: \jobname-js.tex Set1 bib } + \ht:special {t4ht@DCopyTo: \jobname-js.tex Cont bib } + \ht:special {t4ht@DCopyTo: \jobname-js.tex Set2 bib } + \ht:special {t4ht@DCopyTo: \jobname-js.tex Skip bib } +B5 +\ht:special {t4ht@DCopyTo: \jobname-js.tex Until bib } +B6 +\EndVerbatim + +produces the string ` B1 B3 '. + + + + +\<CopyTo files\><<< +{ `<CopyTo vars`> + eoln_ch = (int) 'x'; + while( eoln_ch != EOF ) { + status = scan_str("CopyTo: ", TRUE, lg_file); + status = scan_until_str(" ", 1, status, lg_file); + status = scan_until_str(" ", 2, status, lg_file); + status = scan_until_str(" ", 3, status, lg_file); + status = scan_until_str(" ", 4, status, lg_file); + status = scan_until_end_str("", 5, status, lg_file); + if( status ){ + if( debug ){ + (IGNORED) printf("...CopyTo: %s%s%s%s%s...\n", + match[1], match[2], match[3], match[4], match[5]); + } + rec_op = eq_str(match[2],"From ")? From_op : + ( eq_str(match[2],"Until ")? Until_op : + ( eq_str(match[2],"Skip ")? Skip_op : + ( eq_str(match[2],"Cont ")? Cont_op : No_op ))); + if( rec_op == No_op ){ `<try Addr and Set ops`> } + if( rec_op == No_op ){ + (IGNORED) fprintf(stderr,"--- warning --- "); + (IGNORED) fprintf(stderr,"CopyTo: %s%s%s%s%s?\n", + match[1], match[2], match[3], match[4], match[5]); + } else { + `<find file records`> + `<find to-from record`> + `<find group record`> + `<enter op record`> + `<act on op`> + } } } + `<release CopyTo resources`> +} +>>> + + +\<try Addr and Set ops\><<< +ch = match[2]; +if( (ch[0]=='S') && (ch[1]=='e') && (ch[2]=='t') ){ + ch += 3; rec_op = Set_op; +} else if( (ch[0]=='A') && (ch[1]=='d') && (ch[2]=='d') && (ch[3]=='r') ){ + ch += 4; rec_op = Addr_op; +} +if( rec_op != No_op ){ + addr = 0; while( (*ch>='0') && (*ch<='9') ){ + addr = addr*10 + *ch - '0'; ch++; +} } +>>> + +\<release CopyTo resources\><<< +for( p = opened_files; p != (struct files_rec*) 0; ){ + (IGNORED) fclose(p->file); + free((void *) p->name); + `<free to-from records`> + p1= p; p = p->right; free((void *) p1); +} +>>> + +\<free to-from records\><<< +for( p1 = p->down; p1 != (struct files_rec*) 0; ){ + `<free group records`> + p2 = p1; p1 = p1->right; free((void *) p2); +} +>>> + +\<free group records\><<< +for( p2 = p1->down; p2 != (struct files_rec*) 0; ){ + `<free op records`> + p3 = p2; p2 = p2->right; free((void *) p3); +} +>>> + +\<free op records\><<< +for( p3 = p2->down; p3 != (struct files_rec*) 0; ){ + p4 = p3; p3 = p3->down; free((void *) p4); +} +>>> + + + + + +\<act on op\><<< +if( rec_op == Until_op ){ + for( p = to_rec->down; + p != (struct files_rec*) 0; p = p->down ){ + if( p->op == From_op ){ from_op = p; break; } + } + if( p == (struct files_rec*) 0 ){ + `<missing From for CopyTo`> + } else { + `<perform ops`> + `<remove ops`> + } +} +>>> + + + + +\<perform ops\><<< +in_file = from_rec->file; +out_file = to_rec->file; +start_loc = from_op->loc; +write_on = TRUE; +(IGNORED) fseek(in_file, (long) start_loc, `<abs file addr`>); +for( p= from_op; p != to_rec; p = p->up ){ + switch( p->op ){ + case Until_op:{ `<Until op`> break; } + case Skip_op:{ `<Skip op`> break; } + case Cont_op:{ `<Cont op`> break; } + case Set_op:{ `<Set op`> break; } + default: { } +} } +>>> + + +\<Until op\><<< +if( write_on ){ + end_loc = p->loc; + for(; start_loc<end_loc; start_loc++) { + (IGNORED) putc( getc(in_file), out_file ); +} } +>>> + + +\<Skip op\><<< +if( write_on ){ + end_loc = p->loc; + for(; start_loc<end_loc; start_loc++) { + (IGNORED) putc( getc(in_file), out_file ); + } +} +write_on = FALSE; +>>> + + +\<Cont op\><<< +end_loc = p->loc; +if( write_on ){ + for(; start_loc<end_loc; start_loc++) { + (IGNORED) putc( getc(in_file), out_file ); + } +} else { + start_loc = end_loc; + (IGNORED) fseek(in_file, (long) end_loc, `<abs file addr`>); +} +write_on = TRUE; +>>> + + +\<Set op\><<< +addr = -1; +for( p1 = from_op->up; p1 != to_rec; p1 = p1->up ){ + if( (p1->op == Addr_op) && (p1->label == p->label) ){ + addr = p1->loc; break; +} } +if( addr != -1 ){ (p->up)->loc = addr; } +>>> + + +\<remove ops\><<< +to_rec->down = from_op->down; +if( from_op->down != (struct files_rec*) 0){ + (from_op->down)->up = to_rec; +} +for( p = from_op; p != to_rec; ){ + p1 = p; p = p->up; free((void *) p1); +} +if( to_rec->down == (struct files_rec*) 0){ + if( to_rec->left == (struct files_rec*) 0 ){ + (to_rec->up)->down = to_rec->right; + } else { + (to_rec->left)->right = to_rec->right; + } + if( to_rec->right != (struct files_rec*) 0 ){ + (to_rec->right)->left = to_rec->left; + } + p1 = to_rec; to_rec = to_rec->up; free((void *) p1); +} +>>> + +\<missing From for CopyTo\><<< +(IGNORED) fprintf(stderr,"%sMissing ``CopyTo From':\n", "--- warning --- "); +for( p = to_rec->down; p != (struct files_rec*) 0; p = p->down ){ + (IGNORED) fprintf(stderr," %s %s%d %s\n", to_rec->name, + p->op == From_op ? "From " : + ( p->op == Until_op ? "Until " : + ( p->op == Skip_op ? "Skip " : + ( p->op == Cont_op? "Cont " : + ( p->op == Addr_op? "Addr " : + ( p->op == Set_op? "Set " : "No_op " ))))), + p->loc, from_rec->name + ); +} +>>> + + + + +\<enter op record\><<< +p = m_alloc(struct files_rec, 1); +p->down = to_rec->down; to_rec->down = p; +p->up = to_rec; +if( p->down != (struct files_rec*) 0 ){ + (p->down)->up = p; +} +*(match[4] + (int) strlen((char *) match[4]) - 1) = '\0'; +p->loc = (int) get_long_int(match[4]); +p->op = rec_op; +p->label = addr; +>>> + +\<find group record\><<< +if( to_rec->down == (struct files_rec*) 0 ){ + `<add first group record`> +} else { + to_rec = to_rec->down; + for( p = to_rec->right; p != (struct files_rec*) 0; p = p->right ){ + if( eq_str(to_rec->group,match[3]) ){ break; } + to_rec = p; + } + if( !eq_str(to_rec->group,match[3]) ){ + `<add next group record`> +} } +>>> + + + +\<add first group record\><<< +to_rec->down = p = m_alloc(struct files_rec, 1); +p->up = to_rec; +p->right = p->left = p->down = (struct files_rec*) 0; +p->name = to_rec->name; +p->file = to_rec->file; +p->from_rec = from_rec; +p->loc = -1; +p->op = No_op; +p->group = m_alloc(char, (int) strlen((char *) match[3]) + 1); +(IGNORED) strcpy((char *) p->group, (char *) match[3] ); +to_rec = p; +>>> + +\<add next group record\><<< +to_rec->right = p = m_alloc(struct files_rec, 1); +p->left = to_rec; +p->right = p->down = (struct files_rec*) 0; +p->up = to_rec->up; +p->name = to_rec->name; +p->file = to_rec->file; +p->from_rec = from_rec; +p->loc = -1; +p->group = m_alloc(char, (int) strlen((char *) match[3]) + 1); +(IGNORED) strcpy((char *) p->group, (char *) match[3] ); +to_rec = p; +>>> + + + +\<find to-from record\><<< +if( to_rec->down == (struct files_rec*) 0 ){ + `<add first to-from record`> +} else { + to_rec = to_rec->down; + for( p = to_rec->right; p != (struct files_rec*) 0; p = p->right ){ + if( to_rec->from_rec == from_rec ){ break; } + to_rec = p; + } + if( to_rec->from_rec != from_rec ){ + `<add next to-from record`> +} } +>>> + +\<add first to-from record\><<< +to_rec->down = p = m_alloc(struct files_rec, 1); +p->up = to_rec; +p->right = p->left = p->down = (struct files_rec*) 0; +p->name = to_rec->name; +p->file = to_rec->file; +p->from_rec = from_rec; +p->loc = -1; +p->op = No_op; +to_rec = p; +>>> + +\<add next to-from record\><<< +to_rec->right = p = m_alloc(struct files_rec, 1); +p->left = to_rec; +p->right = p->down = (struct files_rec*) 0; +p->up = to_rec->up; +p->name = to_rec->name; +p->file = to_rec->file; +p->from_rec = from_rec; +p->loc = -1; +to_rec = p; +>>> + + +\<find file records\><<< +file_name = match[1]; +*(file_name + (int) strlen((char *) file_name) - 1) = '\0'; +strcpy((char *) file_mode, WRITE_TEXT_FLAGS); +for(i=1; i<=2; i++){ + `<search CopyTo file`> + file_name = match[5]; + strcpy((char *) file_mode, `<CopyTo read flags`>); +} +>>> + + + + + + + + + +\<search CopyTo file\><<< +for( p = opened_files; p != (struct files_rec*) 0; p = p->right ){ + if( eq_str(file_name,p->name) ) { break; } +} +if( p == (struct files_rec*) 0 ){ + p = m_alloc(struct files_rec, 1); + p->right = opened_files; opened_files = p; + p->down = (struct files_rec*) 0; + strcpy((char *) p->file_mode, (char *) file_mode); + p->name = m_alloc(char, (int) strlen((char *) file_name) + 1); + (IGNORED) strcpy((char *) p->name, (char *) file_name ); + if( (p->file = fopen(file_name, file_mode)) == NULL ) + { (IGNORED) warn_i_str(5,file_name); } +} +to_rec = from_rec; from_rec = p; +>>> + + +\<defines\><<< +struct files_rec{ + FILE* file; + char *name, *group, op; + Q_CHAR file_mode[5]; + int loc, label; + struct files_rec *from_rec, *right, *left, *down, *up; +}; +#define No_op 0 +#define From_op 1 +#define Until_op 2 +#define Skip_op 3 +#define Cont_op 4 +#define Addr_op 5 +#define Set_op 6 +>>> + +\<CopyTo vars\><<< +Q_CHAR *file_name, file_mode[5]; +int i, start_loc, end_loc, addr = 0; +char rec_op, *ch; +static struct files_rec *to_rec, *from_rec, + *opened_files = (struct files_rec *) 0, + *p, *p1, *p2, *p3, *p4, *from_op; +FILE *in_file, *out_file; +BOOL write_on; +>>> + + + + + + + + + + + + + + + + +%%%%%%%%%%%%%%%%%%%%%%% +\Section{post-process ext files} +%%%%%%%%%%%%%%%%%%%%%%% + +\<post-process ext files\><<< +if( `<ext-script`> ){ + eoln_ch = (int) 'x'; + while( eoln_ch != EOF ) { + status = scan_str("File: ", TRUE, lg_file); + status = scan_until_str(".", 1, status, lg_file); + status = scan_until_end_str("", 2, status, lg_file); + if( status ){ Q_CHAR *ext; + struct script_struct *cur_script; + ext = match[1]; + (IGNORED) strct( ext, match[2] ); + ext += strlen((char *) ext); + while( *(--ext) != '.' ){ ; } + *ext = '\0'; ext++; + `<get script for ext`> + (void) execute_script(cur_script, + match[1], Dotfield? Dotfield : "", "", ""); + `<release script for ext`> +} } } +>>> + + +\<get script for ext\><<< +{ + struct script_struct *cur, *add, *temp; + Q_CHAR extPlus[256]; + cur = `<ext-script`>; + add = cur_script = NULL_SCRIPT; + while( cur ){ + `<ext = ext + choise`> + if( strpre(extPlus, cur->command) ){ + `<temp = ext command`> + if( cur_script == NULL_SCRIPT ){ + cur_script = add = temp; + } else { + add = add->next = temp; + } } + cur = cur->next; +} } +>>> + + + +\<ext = ext + choise\><<< +(IGNORED) strcpy((char *) extPlus, (char *) ext); +/* + if ( envChoice ) { + (IGNORED) strct ( extPlus, envChoice ); + } +*/ +(IGNORED) strct ( extPlus, " " ); +>>> + +\<temp = ext command\><<< +temp = (struct script_struct *) + m_alloc(struct script_struct, (int) 1); +temp->command = m_alloc(char, (int) strlen((char *) cur->command) + 1); +temp->next = NULL_SCRIPT; +(IGNORED) strcpy((char *) temp->command, + (char *) cur->command + (int) strlen((char *) extPlus) ); +>>> + +\<release script for ext\><<< +while( cur_script != (struct script_struct*) 0 ){ + struct script_struct *temp; + temp = cur_script; cur_script = cur_script->next; free((void *) temp); +} +>>> + + +\<header functions\><<< +static BOOL strpre( ARG_II(char *,char *) ); +>>> + +\<functions\><<< +`[ +static BOOL strpre(s1,s2) + char * s1`; + char * s2 +;{ int i; + for( i=0; i < (int) strlen((char *) s1); i++){ + if( *(s1+i) != *(s2+i) ){ return FALSE; } + } + return TRUE; +} +>>> + + + +\<ext-script\><<< +ext_script +>>> + + + +\<defines\><<< +struct env_c_rec{ + Q_CHAR *option; + struct env_c_rec *next; +}; +>>> + +\<vars\><<< +static struct env_c_rec *envChoice + = (struct env_c_rec*) 0; +>>> + + +\<env blocks selector\><<< +struct env_c_rec *temp = (struct env_c_rec*) + m_alloc(struct env_c_rec, (int) 1); +temp->option = q; +temp->next = envChoice; +envChoice = temp; +>>> + +\<env-skip = skip segment match[1]\><<< +if( envChoice == (struct env_c_rec*) 0 ){ + env_skip = !eq_str(match[1], "default" ); +} else { + struct env_c_rec *p; + env_skip = TRUE; + for( p=envChoice; p!=(struct env_c_rec*) 0 ; p = p->next ){ + if( eq_str(match[1], p->option ) ){ env_skip = FALSE; } +} } +>>> + + + + +%%%%%%%%%%%%%%%%%%%%%%% +\Section{post-process files} +%%%%%%%%%%%%%%%%%%%%%%% + + +\<post-process files\><<< +if( `<file-script`> ){ + eoln_ch = (int) 'x'; + while( eoln_ch != EOF ) { + status = scan_str("File: ", TRUE, lg_file); + status = scan_until_str(".", 1, status, lg_file); + status = scan_until_end_str("", 2, status, lg_file); + if( status ){ Q_CHAR *p; + p = match[1]; + (IGNORED) strct( p, match[2] ); + p += strlen((char *) p); + while( *(--p) != '.' ){ ; } + *p = '\0'; p++; + (void) execute_script(file_script, match[1], + p, Xfield? Xfield : "", ""); +} } } +>>> + +\<file-script\><<< +file_script +>>> + +%%%%%%%%%%%%%%%%%%%%%%% +\Section{User Commands} +%%%%%%%%%%%%%%%%%%%%%%% + +\`'l. 10 --- needs --- "ls *" ---' + +\<process user commands\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { Q_CHAR *command, ch; + int n; + struct sys_call_rec *p; + BOOL flag; + status = scan_str("l. ", TRUE, lg_file); + status = scan_until_str(" --- needs --- \"", 1, status, lg_file); + status = scan_until_str("\" ---", 2, status, lg_file); + if( status ){ + command = match[2]; + *(command + (int) strlen((char *) command) - 5) = '\0'; + `<flag = permission for system calls`> + if( flag ){ + `<execute system command`> + } else { (IGNORED) printf( + "No permission for system call: %s\n", command); } +} } +>>> + + +\<env permissions for system calls\><<< +{ struct sys_call_rec *q; + q = m_alloc(struct sys_call_rec, 1); + q->next = system_calls; + q->filter = match[1]; + match[1] = (Q_CHAR *) malloc(70); max_match[1] = 70; + system_calls = q; +if( debug ){ + (IGNORED) printf(".......'S' script: '%s'\n", + q->filter); } +} +>>> + +\<permission for system calls\><<< +{ struct sys_call_rec *q; + q = m_alloc(struct sys_call_rec, 1); + q->next = system_calls; + q->filter = p + 2; + system_calls = q; +} +>>> + + +\<flag = permission for system calls\><<< +flag = FALSE; +p = system_calls; +while( p ){ + if( (n = (int) strlen((char *) p->filter)) == 1 ) { + if( *(p->filter) == '*' ){ + flag = TRUE; break; + } + } + if( strlen((char *) command) >= (unsigned int) n ) { + ch = command[n]; command[n] = '\0'; + flag = flag || eq_str(p->filter,command); + command[n] = ch; + } + p = p->next; +} +>>> + +\<defines\><<< +struct sys_call_rec{ + Q_CHAR * filter; + struct sys_call_rec *next; +}; +>>> + + +\<vars\><<< +static BOOL system_yes; +static struct sys_call_rec *system_calls = (struct sys_call_rec *) 0; +>>> + + + + + + + + +From log files \`'l. # --- needs --- "command" ---' + + + + + + + + + + +%%%%%%%%%%%%% +\Section{CSS} +%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Record HTFCSS Entries from the lg File} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +The htfcss records are stored in the following linked list, and used +when the font entries `Font("key","...","...","...")' are loaded +(Section~'\Link{usehtfcc}{}\Ref{usehtfcc}\EndLink'). + +\<vars\><<< +static struct htf_struct *htf_rec = (struct htf_struct *) 0; +>>> + + +\<defines\><<< +struct htf_struct{ + Q_CHAR *key, *body, *media; + struct htf_struct *next; +}; +>>> + + + + + +\<htfcss from lg\><<< +{ struct htf_struct *last_rec, *p; + last_rec = (struct htf_struct *) 0; + eoln_ch = (int) 'x'; + while( eoln_ch != EOF ) { + status = scan_str("htfcss: ", TRUE, lg_file); + status = scan_until_end_str("", 1, status, lg_file); + `<remove leading spaces`> + if( status ){ Q_CHAR *key, *body, *media; + media = body = key = match[1]; + `<process htfcss line`> + } } +} +>>> + +\<remove leading spaces\><<< +if( status ){ + Q_CHAR *s, *t; + int i; + s = t = match[1]; + for( i=0; *s == ' '; s++ ) { i++; } + if( i>0 ){ + while( *s != 0 ){ + *(t++) = *(s++); + } + *t = 0; +} } +>>> + + +?? How the case `append prev htfcss rec' can be reached ?? + +\<process htfcss line\><<< +while( *body && (*body != ' ') ){ body++; } +if( *body == ' ' ){ media = body; *(body++) = '\0'; } +`<extract media info`> +if( *body ){ + if( *key ){ `<add new htfcss rec`> } +#if 0 /* unreachable */ + else if( last_rec ){ `<append prev htfcss rec`> } +#endif /* 0, unreachable */ +} +>>> + +\<extract media info\><<< +if( (int) strlen((char *) body) > 6 ){ + if( (*(body) == '@') + && (*(body+1) == 'm') + && (*(body+2) == 'e') + && (*(body+3) == 'd') + && (*(body+4) == 'i') + && (*(body+5) == 'a') ) + { + body += 6; + while( *body == ' ' ){ body++; } + media = body; + while( (*body != ' ') && (*body != '\0') ){ body++; } + if( *body == ' ' ){ *(body++) = '\0'; } + while( *body == ' ' ){ body++; } +} } +>>> + +\<add new htfcss rec\><<< +p = m_alloc(struct htf_struct, 1); +p->next = (struct htf_struct *) 0; +p->key = m_alloc(char, (int) strlen((char *) key) + 1); +(IGNORED) strcpy((char *) p->key, (char *) key ); +p->media = m_alloc(char, (int) strlen((char *) media) + 1); +(IGNORED) strcpy((char *) p->media, (char *) media ); +p->body = m_alloc(char, (int) strlen((char *) body) + 1); +(IGNORED) strcpy((char *) p->body, (char *) body ); +if( last_rec ){ + last_rec->next = p; last_rec = p; +} else { + htf_rec = last_rec = p; +} +if( debug ){ + (IGNORED) printf(".......%s...%s...%s\n", key, media, body); +} +>>> + +\<append prev htfcss rec\><<< +last_rec->body = (Q_CHAR *) r_alloc((void *) last_rec->body, + (size_t) strlen((char *) last_rec->body) + + (size_t) strlen((char *) body) + + 2); +(IGNORED) strct(last_rec->body,"\n"); +(IGNORED) strct(last_rec->body,body); +if( debug ){ + (IGNORED) printf(".......%s\n", body); +} +>>> + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Font-Css-Plus Entries from The lg File} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +The command \`'\Configure{htf-css}{cmmi}{font-style: italic;}' +provides in the lg file an entry of the form +\`'Font_Css_Plus cmmi font-style: italic;'. + +\<font=(...) from lg\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("Font_Css_Plus ", TRUE, lg_file); + status = scan_until_str(" ", 1, status, lg_file); + status = scan_until_end_str("", 2, status, lg_file); + if( status ){ Q_CHAR *key; + key = match[1]; + *(key + (int) strlen((char *) key) - 1) = '\0'; + `<store font style of lg`> +} } +>>> + + + +\<store font style of lg\><<< +if( (*key != '\0') && (*key != '\n') ) { + struct htf_struct *p; + p = m_alloc(struct htf_struct, 1); + p->next = htf_rec; + htf_rec = p; + p->key = m_alloc(char, (int) strlen((char *) key) + 1); + (IGNORED) strcpy((char *) p->key, (char *) key ); + p->body = m_alloc(char, (int) strlen((char *) match[2]) + 1); + (IGNORED) strcpy((char *) p->body, (char *) match[2] ); + if( debug ){ + (IGNORED) printf(".......%s...%s\n", key, match[2]); +} } +>>> + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Imported Css File} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + +%Css: TD.caption{white-space: nowrap; } +%Font("cmex","10","100") +%Font("cmmi","10","100") +%Font("cmmi","5","100") +%Font("cmmi","7","100") +%Font("cmr","10","100") +%Font("cmr","5","100") +%Font("cmr","7","100") +%Font("cmsy","10","100") +%Font("cmsy","7","100") +%Font("cmti","10","100") +%Font("cmtt","10","100") +%Font_Class(1,""): <IMG SRC=""ALT=""CLASS="%s%s-%d--%x"> +%Font_Class(3,"mva"): <IMG SRC=""ALT=""CLASS="%s-%d--%x"ALIGN="MIDDLE"> +%Font_Class(6,"ul"): <SPAN CLASS="underline"></SPAN> +%Font_Css("sc"): .small-caps{font-variant: small-caps; } +% Font_Css("ul"): .underline{text-decoration:underline; } + + + + +\<process css\><<< +{ + Q_CHAR css_name[255]; + FILE *css_file, *tmp_file; + BOOL css_sty; + `<css-file = open file ...`> + if( css_file ){ + (IGNORED) printf ("Entering %s\n", css_name); + tmp_file = fopen(tmp_name, WRITE_TEXT_FLAGS); + if( !tmp_file ) { + (IGNORED) warn_i_str(5,tmp_name); + } else { `<c: tex4ht.tmp := css file`> } + tmp_file = open_file(tmp_name, ".tmp"); + css_file = fopen(css_name, WRITE_TEXT_FLAGS); + if( !tmp_file ) { + (IGNORED) warn_i_str(5,tmp_name); + } else if( !css_file ) { + (IGNORED) warn_i_str(5,css_name); + } else { + `<c: css file = header of tex4ht.tmp`> + if( css_sty ){ + `<css file = css.sty`> + `<css file = tail of tex4ht.tmp`> + } + } + (IGNORED) fclose(tmp_file); + (IGNORED) fclose(css_file); +} } +>>> + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Preliminary Processing of the CSS File} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\<c: tex4ht.tmp := css file\><<< + int ch; +while( (ch = getc(css_file)) != EOF ) { + (IGNORED) putc( ch, tmp_file ); +} +(IGNORED) fclose(tmp_file); +(IGNORED) fclose(css_file); +>>> + + +\<css-file = open file ...\><<< +(IGNORED) strcpy((char *) css_name, (char *) job_name); +(IGNORED) strct(css_name, ".css"); +css_file = fopen(css_name, READ_TEXT_FLAGS); +>>> + +\SubSection{Cotributors to the Css File} + +Copy until insertion point: + +\`'/* css.sty */' + +\<c: css file = header of tex4ht.tmp\><<< +css_sty = FALSE; +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_until_end_str("", 1, TRUE, tmp_file); + `<match[2] := compressed match[1]`> + if( eq_str(match[2], "/*css.sty*/") ){ css_sty = TRUE; break; } + (IGNORED) fprintf(css_file, "%s\n", match[1]); +} +>>> + +\<vars\><<< +static BOOL status; +>>> + + + +\<match[2] := compressed match[1]\><<< +{ Q_CHAR *p, *q; + int n; + n = 0; p = match[1]; q = match[2]; + while ( (*p != '\0') ){ + if (n == 13) { *(q-10) = '\0'; break;} + if( *p != ' ' ){ *(q++) = *p; n++; } + p++; + } + *q = '\0'; +} +>>> + +Contribution from lg File + + + +\<css file = css.sty\><<< +(IGNORED) fprintf(css_file, "/* start css.sty */\n"); +`<rewind lg file`> `<Font_css_base: ...`> +`<rewind lg file`> `<process Font_Size: ...`> +`<rewind lg file`> `<process Font(...)`> +`<rewind lg file`> `<process Font_Css(...):...`> +`<rewind lg file`> `<process Css:...`> +(IGNORED) fprintf(css_file, "/* end css.sty */\n"); +>>> + + +The \`'<process Css:...>' should be after the other two's to allow +the user to overide with \''\Css' commands the +other contributions. + + + + +We want to remove the non-leading \`'/* css.sty */', just +in case t4ht.perl is called consequtively more than once. + +\<css file = tail of tex4ht.tmp\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_until_end_str("", 1, TRUE, tmp_file); + `<match[2] := compressed match[1]`> + if( !eq_str(match[2], "/*css.sty*/") ){ + (IGNORED) fprintf(css_file, "%s\n", match[1]); + } +} +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Contributions from /Css Commands} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\`'Css: P.noindent { text-indent: 0em }' + +\<process Css:...\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("Css: ", TRUE, lg_file); + status = scan_until_end_str("", 1, status, lg_file); + if( status ){ + (IGNORED) fprintf(css_file, "%s\n", match[1]); +} } +>>> + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Contributions From Font-Size} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\`'\Needs{"Font_Size: 12"}' + + + +\<process Font_Size: ...\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("Font_Size: ", TRUE, lg_file); + status = scan_until_end_str("", 1, status, lg_file); + if( status ){ + base_font_size = (int) get_long_int(match[1]); +} } +>>> + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Contributions to Fonts} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\Link{}{usehtfcc}\EndLink\Tag{usehtfcc}{Contributions to Fonts} + +\`'Font("family_name", "font_size", "design_sz * 100 / 655360 / 10", "mag")' +(e.g., \`'Font("cmr","10","10","100")', +\`'Font("aptmri","8t",??,"100")', +\`'Font("ecti","1095","10","100")') + + + + + + + +\<process Font(...)\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("Font(\"", TRUE, lg_file); + status = scan_until_str("\",\"", 1, status, lg_file); + status = scan_until_str("\",\"", 2, status, lg_file); + status = scan_until_str("\",\"", 3, status, lg_file); + status = scan_until_end_str("\")", 4, status, lg_file); + if( status ){ + Q_CHAR *p; + struct htf_struct *font_sty; + int second; + p = match[1]; + *(p + (int) strlen((char *) p) - 3) = '\0'; + p = match[2]; + *(p + (int) strlen((char *) p) - 3) = '\0'; + p = match[3]; + *(p + (int) strlen((char *) p) - 3) = '\0'; + p = match[4]; + *(p + (int) strlen((char *) p) - 2) = '\0'; + `<get font size`> + `<get font style`> +} } +>>> + + + + + +\<get font style\><<< +font_sty = htf_rec; +while ( font_sty ) { + if( eq_str(font_sty->key,match[1]) ){ + if( *(font_sty->media) == '\0' ){ + `<print font style css`> + second = 100; + } else { + `<print media style`> + } + } + font_sty = font_sty->next; +} +if( second != 100 ){ `<print font style css`> } +>>> + + + + +\<get font size\><<< +{ Q_CHAR *p; + second = (int) + ( (int) get_long_int(match[3]) + * (int) get_long_int(match[4]) + / base_font_size + ); + while( second > 700 ){ second /= 10; } + p = match[3]; + while( *p != '\0' ){ + if( (*p < '0') || (*p > '9') ){ second = 100; break; } + p++; + } + `<inspect font-size argument`> +} +>>> + +The following case handles cases like that of \`'Font("ecti","1095","10","100")', where +\Verb=base_font_size= is 11. + +\<inspect font-size argument\><<< +if( (int) ( (double) get_long_int(match[2]) + / (int) get_long_int(match[4]) + + 0.5 + ) + == base_font_size +){ + second = 100; +}; +>>> + + + + + + + + +\<Font_css_base: ...\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("Font_css_base: ", TRUE, lg_file); + status = scan_until_str("Font_css_mag: ", 1, status, lg_file); + status = scan_until_end_str("", 2, status, lg_file); + if( status ){ + Font_css_base = match[1]; + *(Font_css_base + (int) strlen((char *) Font_css_base) - 14) = '\0'; + match[1] = (Q_CHAR *) malloc(70); max_match[1] = 70; + Font_css_mag = match[2]; + match[2] = (Q_CHAR *) malloc(70); max_match[2] = 70; +} } +>>> + + + + +\<vars\><<< +static char *Font_css_base = NULL, + *Font_css_mag = NULL; +static int base_font_size = 10; +>>> + + + +\<print font style css\><<< +(IGNORED) fprintf(css_file, + (Font_css_base == NULL)? ".%s-%s" : Font_css_base, + match[1], match[2]); +if( !eq_str(match[4],"100") ){ + (IGNORED) fprintf(css_file, + (Font_css_mag == NULL)? "x-x-%s" : Font_css_mag, + match[4]); +} +(IGNORED) fprintf(css_file, "{"); +if( (second < 98) || (second > 102) ){ + (IGNORED) fprintf(css_file, "font-size:%d%c;", second, '%'); +} +if( font_sty ) { + (IGNORED) fprintf(css_file, "%s", font_sty->body); +} +(IGNORED) fprintf(css_file, "}\n"); +>>> + + +\<print media style\><<< +(IGNORED) fprintf(css_file, "@media %s{", font_sty->media); +(IGNORED) fprintf(css_file, + (Font_css_base == NULL)? ".%s-%s" : Font_css_base, + match[1], match[2]); +if( !eq_str(match[4],"100") ){ + (IGNORED) fprintf(css_file, + (Font_css_mag == NULL)? "x-x-%s" : Font_css_mag, + match[4]); +} +(IGNORED) fprintf(css_file, "{"); +if( font_sty ) { + (IGNORED) fprintf(css_file, "%s", font_sty->body); +} +(IGNORED) fprintf(css_file, "}}\n"); +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Font-Css Contributions} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\`'Font_Css("4"): .small-caps{font-variant: small-caps; }' + +\<process Font_Css(...):...\><<< +{ char *font_class [256]; + int last_class; + `<find usage`> + eoln_ch = (int) 'x'; + while( eoln_ch != EOF ) { + status = scan_str("Font_Css(\"", TRUE, lg_file); + status = scan_until_str("\"): ", 1, status, lg_file); + status = scan_until_end_str("", 2, status, lg_file); + if( status ){ int i; + for(i=0; i<last_class; i++){ + if( eq_str(match[1],font_class[i]) ){ + (IGNORED) fprintf(css_file, "%s\n", match[2]); + break; +} } } } } +>>> + + + +\<find usage\><<< +last_class = 0; +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { + status = scan_str("Font_Class(", TRUE, lg_file); + status = scan_until_str(",\"", 1, status, lg_file); + status = scan_until_str("\"): ", 1, status, lg_file); + status = scan_until_end_str("", 2, status, lg_file); + if( status ){ + font_class[last_class++] = match[1]; + match[1] = (Q_CHAR *) malloc(7); max_match[1] = 7; +} } +`<rewind lg file`> +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\Section{Load Env File} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Retrieve Info} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\<load env file\><<< +{ FILE* file; + U_CHAR env_loc[512]; + env_loc[0] = '\0'; + `<find tex4ht.env`> + if( file ){ + `<get info from env file`> + (IGNORED) fclose(file); +} } +>>> + + +% (IGNORED) printf("Entering %s\n", env_loc[0]? &env_loc[0] +% :"tex4ht.env"); + + + +\<get info from env file\><<< +eoln_ch = (int) 'x'; +while( eoln_ch != EOF ) { Q_CHAR ch; + ch = (char) (eoln_ch = getc(file)); + if( eoln_ch != (int) '\n' ){ + status = scan_until_end_str("", 1, TRUE, file); + if( status ){ + switch( ch ){ + case 'A':{ `<script for chmod`> break;} + case 'C':{ `<script for copy`> break;} + case 'E':{ `<script for empty gifs`> break;} + case 'F':{ `<script for dvigif of glyps`> break;} + case 'G':{ `<script for dvigif`> break;} + case 'M':{ `<script for move`> break;} + case 'S':{ `<env permissions for system calls`> break;} + case 'X':{ `<script for file`> break;} + case '.':{ `<script for file ext`> break;} + case '<':{ `<env selector`> break;} + default:{ } +} } } } +>>> + + + + + +\<script for dvigif of glyps\><<< +if( debug ){ + (IGNORED) printf(".......'F' script\n"); } +dvigif_glyp_script = add_script(dvigif_glyp_script); +>>> + + +\<script for move\><<< +if( debug ){ + (IGNORED) printf(".......'M' script\n"); } +move_script = add_script(move_script); +>>> + + +\<script for copy\><<< +if( debug ){ + (IGNORED) printf(".......'C' script\n"); } +copy_script = add_script(copy_script); +>>> + + + + + +\<script for file\><<< +if( debug ){ + (IGNORED) printf(".......'X' script\n"); } +`<file-script`> = add_script(`<file-script`>); +>>> + +\<script for file ext\><<< +if( debug ){ + (IGNORED) printf(".......'.' script\n"); } +`<ext-script`> = add_script(`<ext-script`>); +>>> + + + + +\<script for chmod\><<< +if( debug ){ + (IGNORED) printf(".......'A' script\n"); } +chmod_script = add_script(chmod_script); +>>> + +\<script for empty gifs\><<< +if( debug ){ + (IGNORED) printf(".......'E' script\n"); } +empty_fig_script = add_script(empty_fig_script); +>>> + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Utilities for Retrieving Info} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\<env selector\><<< +if( *(match[1]) != '/' ){ + U_CHAR *p; + BOOL env_skip; + for( p = match[1]; + (*p != '>') && (*p != '\n') && (*p != EOF ) ; + p++ ){} + if( *p == '>' ){ *p = '\0'; } + `<env-skip = skip segment match[1]`> + if( env_skip ){ + `<skip env segment`> + } else { + if( debug ){ + (IGNORED) printf("....... <%s>\n", match[1]); + } + } +} else if( debug ){ + (IGNORED) printf("....... <%s\n", match[1]); +} +>>> + +\<skip env segment\><<< + U_CHAR cur_block[90]; +if( debug ){ + (IGNORED) printf("....... <%s> skipping ...\n", match[1]); +} +(IGNORED) strcpy((char *) cur_block, (char *) match[1]); +status = FALSE; +while( !status && (eoln_ch != EOF) ){ + status = scan_str("</", TRUE, file); + status = scan_until_str(">", 1, status, file); + status = scan_until_end_str("", 2, status, file); + if( status ){ + *(match[1] + strlen((char *) match[1]) - 1) = '\0'; + status = eq_str(match[1], cur_block); + if( debug ){ + (IGNORED) printf("....... </%s>\n", match[1]); +} } } +>>> + + + +\<header functions\><<< +static struct script_struct * add_script( ARG_I(struct script_struct *) ); +>>> + +\<functions\><<< +`[ +static struct script_struct * add_script(script) + struct script_struct * script +;{ + struct script_struct* temp, * q; + temp = (struct script_struct *) + m_alloc(struct script_struct, (int) 1); + temp->command = match[1]; + if( debug ){ + (IGNORED) printf("....... %s\n", temp->command); } + temp->next = NULL_SCRIPT; + match[1] = (Q_CHAR *) malloc(70); + max_match[1] = 70; + if( script ){ + q = script; + while( q->next ){ q = q->next; } + q->next = temp; + } else { + script = temp; + } + return script; +} +>>> + + + + + + + + + +\<defines\><<< +struct script_struct{ + Q_CHAR *command; + struct script_struct *next; +}; +>>> + +\<vars\><<< +static struct script_struct + * dvigif_script = NULL_SCRIPT, + * dvigif_glyp_script = NULL_SCRIPT, + * move_script = NULL_SCRIPT, + * empty_fig_script = NULL_SCRIPT, + * copy_script = NULL_SCRIPT, + * `<file-script`> = NULL_SCRIPT, + * `<ext-script`> = NULL_SCRIPT, + * chmod_script = NULL_SCRIPT; +>>> + +\<defines\><<< +#define NULL_SCRIPT (struct script_struct *) 0 +>>> + + + + + + + + +% case 'H':{ `<env-htf-sty = htfcss.env file`> break;} +% +% \<env-htf-sty = htfcss.env file\><<< +% env_htf_sty = match[1]; +% match[1] = (Q_CHAR *) malloc(70); +% max_match[1] = 70; +% if( debug ){ +% (IGNORED) printf(".......'H' script: '%s'\n", +% env_htf_sty); } +% >>> +% +% \<vars\><<< +% static Q_CHAR* env_htf_sty = Q_NULL; +% >>> + + + +\Verbatim +% dvips -mode ibmvga -D 110 -f foo.idv -pp 92 > tmp.ps +% convert -crop 0x0 -density 110x110 -transparent '#FFFFFF' tmp.ps foo.gif +Gdvips -mode ibmvga -D 110 -f %1 -pp %2 > tmp.ps +Gconvert -crop 0x0 -density 110x110 -transparent '#FFFFFF' tmp.ps %3 +% t4ht -d%2 +Mmv %1 %2%3 +Ccp %1 %2%3 +% t4ht -d%2 -m%1 +Achmod %1 %2%3 +H/n/gold/5/gurari/tex4ht.dir/ +\EndVerbatim + + + +\SubSection{Open Directory} + +\<env file at work dir\><<< +if( !file ) { + if( debug ){ + (IGNORED) printf("tex4ht.env?\n"); + } + file = f_open("tex4ht.env", READ_TEXT_FLAGS); + (IGNORED) strcpy((char *) &env_loc[0], "tex4ht.env"); + if( debug && file ){ + (IGNORED) printf(".......Open: ./tex4ht.env\n"); } +} +>>> + +\<find tex4ht.env\><<< +{ Q_CHAR str[512], + *TEX4HTENV; + `<env file from command switch`> + `<env file at work dir`> + `<env file .tex4ht`> + `<TEX4HTENV env`> + `<env file at root dir`> + `<ENVFILE env`> + if( !file ) { `<env file from prog loc`> } + `<kpathsea env file`> + if( !file ) warn_i_str( 5, `<warn 1`>); +} +>>> + + + + + + + + +\<TEX4HTENV env\><<< +if( !file ){ + TEX4HTENV = getenv("TEX4HTENV"); + if( TEX4HTENV ){ + if( debug ){ + (IGNORED) printf("%s?\n", TEX4HTENV); + } + file = f_home_open(TEX4HTENV,READ_TEXT_FLAGS); + } +} +>>> + + + + + + +\<env file .tex4ht\><<< +#ifndef DOS_WIN32 + if( !file ) { + if( debug ){ + (IGNORED) printf(".tex4ht?\n"); + } + file = f_open(".tex4ht", READ_TEXT_FLAGS); + (IGNORED) strcpy((char *) &env_loc[0], ".tex4ht"); + if( debug && file ){ + (IGNORED) printf(".......Open: ./.tex4ht\n"); } + } +#endif +>>> + +\<ENVFILE env\><<< +#ifdef ENVFILE + if( !file ) { + if( debug ){ + (IGNORED) printf("%s?\n", ENVFILE); + } + file = f_home_open( ENVFILE,READ_TEXT_FLAGS); + (IGNORED) strcpy((char *) &env_loc[0], (char *) ENVFILE); + if( debug && file ){ + (IGNORED) printf(".......Open: %s\n", ENVFILE); } + } +#endif +>>> + + + +\<h-defines\><<< +#ifndef ENVFILE + +#endif +>>> + + + +\<warn 1\><<< +#ifdef DOS_WIN32 + "tex4ht.env" +#endif +#ifndef DOS_WIN32 + "tex4ht.env | .tex4ht" +#endif +>>> + + + + +\<kpathsea env file\><<< + +#ifdef KPATHSEA +if( !file ) { U_CHAR * envfile; + char *arch, *p, str[256]; + `<arch = tail of SELFAUTOLOC`> + envfile = (char *) 0; + `<envfile = kpse-find-file architecture/tex4ht.env`> + if ( !envfile ){ `<envfile = kpse-find-file tex4ht.env`> } + if ( !envfile ){ `<envfile = kpathsea tex4ht.env`> } + if ( envfile ){ + file = kpse_open_file (envfile, kpse_program_text_format); + (IGNORED) printf("(%s)\n", envfile); + } + if( debug && file ){ + (IGNORED) printf(".......Open kpathsea %s\n", envfile); + } +} +if( debug ){ + U_CHAR *p, *q; + `<trace T4HTINPUTS`> +} +#endif +>>> + +%%%<-- + +\<arch = tail of SELFAUTOLOC\><<< +p = arch = (char *) kpse_var_value( "SELFAUTOLOC" ); +while( *p != '\0' ){ + if( (*p == '/') || (*p == '\\') ){ + arch = p; + } + p++; +} +>>> + + +\<envfile = kpse-find-file architecture/tex4ht.env\><<< +if( arch ){ + (IGNORED) sprintf(str,"%s%ctex4ht.env", arch+1, *arch); + if( debug ){ + (IGNORED) printf( + "kpse_open_file (\"%s\", kpse_program_text_format)?\n", str ); + } + envfile= kpse_find_file (str, kpse_program_text_format, 0); +} +>>> + + +\<envfile = kpse-find-file tex4ht.env\><<< +if( debug ){ + (IGNORED) printf( + "kpse_open_file (\"tex4ht.env\", kpse_program_text_format)?\n"); +} +envfile= kpse_find_file ("tex4ht.env", kpse_program_text_format, 0); +>>> + + +% if( debug ){ +% (IGNORED) printf( "kpse_open_file (\"tex4ht.env\", ...)?\n"); +% } +% envfile= kpse_find_file ("tex4ht.env", kpse_program_text_format, 0); + + + + + + +\<trace T4HTINPUTS\><<< +p = (U_CHAR *) kpse_var_value( "T4HTINPUTS" ); +if( p ){ + (IGNORED) printf("T4HTINPUTS = %s\n", p); +} +q = getenv("T4HTINPUTS"); +if( q ){ (IGNORED) printf( + "Environmet var T4HTINPUTS: %s\n", q); +} +if( !p && !q ){ + (IGNORED) printf( "Missing T4HTINPUTS for kpathsea\n" ); +} +>>> + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{kpathsea vs kpse-find-file} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +The kpathsea utility might succeed where kpse-find-file fails. Maybe due to: +``Kpathsea's subdirectory searching has an + irremediable deficiency: If a directory D being searched for + subdirectories contains plain files and symbolic links to other + directories, but no true subdirectories, D will be considered a + leaf directory, i.e., the symbolic links will not be followed.'' +[\Link[http://www.tug.org/svn/texlive/trunk/Build/source/texk/kpathsea/kpathsea.info?view=markup]{}{}kpathsea.info\EndLink] + + + + +\<envfile = kpathsea tex4ht.env\><<< +if( system("kpsewhich --progname=tex4ht tex4ht.env > tex4ht.tmp") == 0 ){ + `<fileaddr = read tex4ht.tmp`> + envfile= kpse_find_file (fileaddr, kpse_program_text_format, 0); +} +>>> + + + +Don't know how to avoid the use of intermediate file: popen(...) and +fork() are not stadard utilities. Also the redirection \Verb+>+ might +need to be changed, e.g., to \Verb+>&+. + +\<fileaddr = read tex4ht.tmp\><<< +char fileaddr [256]; +int loc = 0; +FILE* file = f_open("tex4ht.tmp", READ_TEXT_FLAGS); +if( file ){ + while( (fileaddr[loc] = getc(file)) >=0 ){ + if( fileaddr[loc] == '\n' ){ fileaddr[loc] = '\0'; break; } + loc++; + } + (IGNORED) fclose(file); +} +>>> + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Root Directory} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\<env file at root dir\><<< +if( !file ){ + if( HOME_DIR ){ (IGNORED) sprintf(str,`<"s/tex4ht.env"`>, HOME_DIR); + if( debug ){ + (IGNORED) printf("%s?\n", str); + } + file = f_open(str,READ_TEXT_FLAGS); + (IGNORED) strcpy((char *) &env_loc[0], (char *) str); + if( debug && file ){ + (IGNORED) printf(".......Open: %s\n", str); } + } +} +#ifndef DOS_WIN32 + if( !file ){ + if( HOME_DIR ){ + (IGNORED) sprintf(str,"%s/.tex4ht", HOME_DIR); + if( debug ){ + (IGNORED) printf("%s?\n", str); + } + file = f_open(str,READ_TEXT_FLAGS); + (IGNORED) strcpy((char *) &env_loc[0], (char *) str); + if( debug && file ){ + (IGNORED) printf(".......Open: %s\n", str); } + } + } +#endif +#if defined(DOS_WIN32) || defined(__MSDOS__) + if( !file ){ + if( debug ){ + (IGNORED) printf("C:/tex4ht.env?\n"); + } + file = f_open("C:/tex4ht.env",READ_TEXT_FLAGS); + (IGNORED) strcpy((char *) &env_loc[0], "C:/tex4ht.env"); + if( debug && file ){ + (IGNORED) printf(".......Open: C:/tex4ht.env\n"); } + } +#endif +>>> + +\<"s/tex4ht.env"\><<< +#if defined(DOS_WIN32) || defined(__DJGPP__) + is_forward_slash(HOME_DIR)? "%s/tex4ht.env" : "%s\\tex4ht.env" +#else + "%s/tex4ht.env" +#endif +>>> + + + + + + + + + + + +\SubSection{Env File from Command Line} + +\<env file from command switch\><<< +if( tex4ht_env_file ){ + if( debug ){ + (IGNORED) printf("%s?\n", tex4ht_env_file); + } + file = f_home_open( tex4ht_env_file, READ_TEXT_FLAGS ); +} else { + file = NULL; +} +if( tex4ht_env_file ){ + (IGNORED) strcpy((char *) &env_loc[0], (char *) tex4ht_env_file); +} +if( debug && file ){ + (IGNORED) printf(".......Open: %s\n", tex4ht_env_file); } +>>> + +\<env file from prog loc\><<< +if( dos_env_file ){ + if( debug ){ + (IGNORED) printf("%s?\n", dos_env_file); + } + file = f_open( dos_env_file, READ_TEXT_FLAGS ) ; + (IGNORED) strcpy((char *) &env_loc[0], (char *) dos_env_file); + if( debug && file ){ + (IGNORED) printf(".......Open: %s\n", dos_env_file); } +} +>>> + + + +Search along the path: command line file $\rightarrow$ work +directory $\rightarrow$ home directory $\rightarrow$ system file. + +\<get .env directory from com ln\><<< +tex4ht_env_file = q; +>>> + +% if( !access(p+2,F_OK) ) tex4ht_env_file = q; +% else warn_i_str(6,q); + + +The function \`'int access(const char *pathname, int mode)', and the mode +\`'F_OK' that tests for the existence of file, are defined in the +following directory. The function returns 0 if ok and -1 on error . + +Where access comes from in dos? + +\<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 +>>> + + + +\SubSection{Env File from Location of t4ht.c} + +\<main's vars\><<< +Q_CHAR * tex4ht_env_file = (Q_CHAR *) 0; +Q_CHAR * dos_env_file = +#if defined(__MSDOS__) + `<get dos env file`>; +#endif +#if !defined(__MSDOS__) + (Q_CHAR *) 0; +#endif + +>>> + + Under DOS, argv[0] usually includes the full path to the program - +even if it wasn't typed in. This can be used to find the program's own +directory, and hence the configuration file. I've implemented this +already as follows: + +\<get dos env file\><<< +get_env_dir(argv[0]) +>>> + +\<functions\><<< +#if defined(__MSDOS__) +`<get tex4ht.env in dos`> +#endif +>>> + +\<get tex4ht.env in dos\><<< +`[ +static char *get_env_dir(progname) + Q_CHAR *progname + +;{ int i; + Q_CHAR *p; + if(! progname || ! *progname) return NULL; `% Safety `% + i = (int) strlen((char *) progname); + while( (progname[--i] != (int) dir_path_slash(progname) ) + && i > 0) ; `%Search for slash`% + if(i == 0) return NULL; `%Not found? Give up`% + p = (Q_CHAR *) malloc(i+12); + if(p == NULL) return NULL; `%Space for new extention after dot`% + strncpy(p, progname, i+1); `%Copy up to slash`% + (IGNORED) strcpy((char *) &p[i+1], + "tex4ht.env"); `%Append new extention`% + return p; +} +>>> + + + + + + +The 12 above is for accomodating \''tex4ht.env'. + + Then, in main(), I changed: + +\`''char* tex4ht_env_file = (Q_CHAR *) 0;' + + to: + +\`'char* tex4ht_env_file = get_env_dir(argv[0]);' + + This works like a charm here, and allows me to use tex4ht from a +different directory without typing a single commandline option. + + + + +\Section{Open Files} + + +\<header functions\><<< +static FILE* f_open( ARG_II(const char*,const char*) ); +>>> + +\<functions\><<< +`[ +static FILE* f_open( name, flags ) + const char* name `; + const char* flags +;{ FILE* file; + if( (file = fopen(name,flags) ) != NULL ) { + (IGNORED) printf("(%s)\n",name); + } + return file; +} +>>> + + + + + +\<header functions\><<< +static FILE* f_home_open( ARG_II(const char*,const char*) ); +>>> + +\<functions\><<< +`[ +static FILE* f_home_open( name, flags ) + const char* name `; + const char* flags +;{ FILE* file; + U_CHAR *str; + if( *name == '~' ){ + if( HOME_DIR ){ + str = m_alloc(char, strlen((char *) HOME_DIR)+strlen(name)); + (IGNORED) sprintf(str,"%s%s", HOME_DIR, name+1); + file = f_open(str,flags); + free((void *) str); + return file; + } else { return NULL; } + } else { return f_open( name, flags ); } +} +>>> + + + + + + +\SubSection{General} + +\<header functions\><<< +static FILE* open_file( ARG_II(const C_CHAR *, const C_CHAR *) ); +>>> + +\<functions\><<< +`[ +static FILE* open_file(name,ext) + const C_CHAR *name`; const C_CHAR *ext +;{ FILE* file; + C_CHAR filename[255], *p; + if( eq_str( ext,LG_EXT ) ) { + (IGNORED) strcpy((char *) filename, (char *) job_name); + (IGNORED) strct(filename, ext); + } else { + (IGNORED) strcpy((char *) filename, name ); + p = filename; + while( TRUE ){ + if( *p == '.' ){ break; } + if( *p == '\0' ){ (IGNORED) strcpy((char *) p, ext); break; } + p++; + } + } + file = fopen(filename, READ_TEXT_FLAGS); + if( !file ) { + (IGNORED) warn_i_str(5,filename); + } else { (IGNORED) printf ("Entering %s\n", filename); } + + return file; +} +>>> + + +We have here a little inconsistency with tex4ht.c. There the input file +name is appended with the extension .dvi, allowing double extensions. +Here, if an extension is present, we remove it before putting .lg on +top of the name. Should we fix that? + + + + +\<defines\><<< +#define LG_EXT ".lg" +>>> + + + + + +% +% \SubSection{htfcss.env} +% +% +% \<file = open htfcss.env\><<< +% if( htf_cfg ){ +% file = open_file(htf_cfg, ".env"); +% } else { C_CHAR filename[255]; +% file = fopen("htfcss.env", READ_TEXT_FLAGS); +% if ( !file && env_htf_sty ){ +% (IGNORED) strcpy((char *) filename, (char *) env_htf_sty); +% (IGNORED) strct(filename, "htfcss.env"); +% file = fopen(filename, READ_TEXT_FLAGS); +% } +% if ( !file ){ +% (IGNORED) strcpy((char *) filename, (char *) HTFDIR ); +% (IGNORED) strct(filename, "htfcss.env"); +% file = fopen(filename, READ_TEXT_FLAGS); +% } +% `<htfcss.env in KPATHSEA`> +% if( !file ) { (IGNORED) warn_i_str(5,"htfcss.env"); } +% else { (IGNORED) printf ("Entering htfcss.env\n"); } +% } +% >>> +% +% + + + +\<mark start lg file\><<< +begin_lg_file = ftell(lg_file); +>>> + +\<rewind lg file\><<< +(IGNORED) fseek(lg_file, begin_lg_file, `<abs file addr`>); +>>> + +\<abs file addr\><<< +0>>> + + + + +\<vars\><<< +static FILE* lg_file; +static long begin_lg_file; +>>> + + + + + +\''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. + + +\<t4ht.h\><<< +#if defined(DOS_WIN32) || defined(__MSDOS__) +#define READ_BIN_FLAGS "rb" +#define READ_TEXT_FLAGS "r" +#define WRITE_BIN_FLAGS "wb" +#ifdef WIN32 +#define WRITE_TEXT_FLAGS "wb" +#else +#define WRITE_TEXT_FLAGS "w" +#endif +#else +#define READ_BIN_FLAGS "r" +#define READ_TEXT_FLAGS "r" +#define WRITE_BIN_FLAGS "w" +#define WRITE_TEXT_FLAGS "w" +#endif +>>> + + + +\Verbatim +I've been held up a bit by a +bug in tex4ht.c that caused emTeX to complain that the created .idv file +was corrupt: + +*** Fatal error 2106: corrupt DVI file (postamble not found) + + I found the cause, though: you open it with mode "w", which is text +mode. Changing this to "wb" solved the problem. +\EndVerbatim + + + + + + + + + +\Section{Utilities} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Error and Warning Messages} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\<signals messages: 2--4\><<< +"Illegal storage address\n", `%2 segmentation`% +"Floating-point\n", `%3 `% +"Interrupt with Cntr-C\n", `%4 `% +>>> + +\<warn and err messages\><<< +`<command line options`>, `%0`% +"Insufficient memory\n", `%1`% +`<signals messages: 2--4`> +"Can't find/open file ``%s'\n", `%5`% +>>> + + + +\<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); +} +>>> + + + + + +\<header functions\><<< +static void warn_i_str( ARG_II(int,const Q_CHAR *) ); +>>> + +\<functions\><<< +`[ +static void warn_i_str(n,str) + int n`; + const Q_CHAR *str + +;{ (IGNORED) fprintf(stderr,"--- warning --- "); + (IGNORED) fprintf(stderr,warn_err_mssg[n], str); +} +>>> + + +% +% \<vars\><<< +% static C_CHAR warning[] = "--- warning --- "; +% >>> + + + + + +\<vars\><<< +static const C_CHAR *warn_err_mssg[]={ `<warn and err messages`> "" }; +>>> + +\<resplit argv for windows\><<< +#ifdef WIN32 + /* See comments in tex4ht */ + 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 +>>> + + + +\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. +\ifHtml[\HPage{more}\Verbatim + Eitan> I also wonder whether the WIN32 really needs to discard the + Eitan> following code fragment. + +signal() is supported through the standard libc, but is mostly +ineffective. An example of the kind of code needed is attached. + + +/* Interrupt handler. mt_exit() is a cleanup_and_exit function */ +#ifdef _WIN32 +BOOL sigint_handler(DWORD dwCtrlType) +{ + mt_exit(3); + return FALSE; /* return value obligatory */ +} +#else +void sigint_handler (int sig) +{ + mt_exit(3); +} +#endif + + /* Catch signals, so we clean up if the child is interrupted. + This emulates "trap 'whatever' 1 2 15". */ +#ifdef _WIN32 + SetConsoleCtrlHandler((PHANDLER_ROUTINE)sigint_handler, TRUE); +#else +# ifdef SIGINT + signal (SIGINT, sigint_handler); +# endif +# ifdef SIGHUP + signal (SIGHUP, sigint_handler); +# endif +# ifdef SIGTERM + signal (SIGTERM, sigint_handler); +# endif +#endif +\EndVerbatim\EndHPage{}]\fi + +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. + + + + +\<header functions\><<< +#ifdef KWIN32 +static BOOL sigint_handler(ARG_I(DWORD)); +#endif +>>> + +\<functions\><<< +#ifdef KWIN32 +`[ +static BOOL sigint_handler(dwCtrlType) DWORD dwCtrlType +;{ + err_i(32); + return FALSE; `% return value obligatory `% +} +#endif +>>> + + +\SubSection{System Calls} + + + +\<vars\><<< +static Q_CHAR command[255]; +static int system_return; +>>> + + +The library \`'<stdlib.h>' includes a function +\`'int system(const char *cmdstring);'. When cmdstring is NULL, +the return value is 0 iff the platform does not support system calls. + + +\<vars\><<< +static BOOL system_yes; +>>> + +\<main's init\><<< +{ C_CHAR *yes = NULL; + system_yes = (`<system exist?`>); +} +>>> + + +Solaris-? issues the command \`'-c: bad option(s)' if we check for the +presence of the system function. + + + +\<system exist?\><<< +#ifdef SYSTEM_FUNCTION_OK +0 +#else +system( yes ) != 0 +#endif +>>> + +\<execute system command\><<< +(IGNORED) call_sys(command); +>>> + + + + +\<header functions\><<< +static void call_sys(ARG_I(Q_CHAR *)); +>>> + + + + +\<functions\><<< +`[ +static void call_sys(command) Q_CHAR * command +;{ + if( *command ){ + (IGNORED) printf("System call: %s\n", command); + system_return = system_yes? (int) system(command) : -1; + (IGNORED) printf("%sSystem return: %d\n", + system_return? "--- Warning --- " : "", system_return ); + if( always_call_sys ){ system_return = 0; } + } +} +>>> + + +\<vars\><<< +static BOOL always_call_sys = FALSE; +>>> + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Strings Concat and compare} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + +\<defines\><<< +#define eq_str(x,y) (!strcmp(x,y)) +>>> + + + +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 *, const C_CHAR *) ); +>>> + +\<functions\><<< +`[ +static void strct( str1, str2 ) + C_CHAR * str1`; + const C_CHAR * str2 + +;{ Q_CHAR * ch; + ch = str1 + (int) strlen((char *) str1); + (IGNORED) strcpy((char *) ch, str2 ); +} +>>> + + + +\SubSection{String into Int} + +\<header functions\><<< +static long int get_long_int( ARG_I(Q_CHAR *) ); +>>> + +\<functions\><<< +`[ +static long int get_long_int(str) + Q_CHAR *str +;{ long int i; + Q_CHAR *ch; + ch = str; i = 0; + while( (*ch>= '0') && (*ch <='9') ){ + i = 10*i + *(ch++) - '0'; + } + return i; +} +>>> + + + +\SubSection{Dynamic Memory Alloc} + + +\<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; +} +>>> + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{myfseek} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +The ftell() and fseek() are not consistent in ms-windows. The ftell() +accounts for \Verb=<cr>= and \Verb=<lf>= in the byte stream, where +fseek() ignore the <cr> bytes. A \Verb=READ_BIN_FLAGS= instead of +\Verb=READ_TEXT_FLAGS= seems to solve the problem. + +\<CopyTo read flags\><<< +READ_BIN_FLAGS +>>> + +A possible alternative is to define a private fseek. + + + +% +% +% (IGNORED) myfseek(in_file, (long) end_loc, `<abs file addr`>); +% +% +% \<header functions\><<< +% static BOOL scan_str( ARG_III(C_CHAR *, BOOL, FILE *) ); +% >>> +% +% \<functions\><<< +% `[ +% static BOOL scan_str(str,flag,file) +% Q_CHAR *str`; +% BOOL flag`; +% FILE* file +% ;{ Q_CHAR *p; +% +% >>> +% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\SubSection{Pattern Recognition Functions} +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +When failure (false \''status') arises, the input line is consumed to +its end. +The \''_until' functions place in ''match[i]' the string found. + +\<header functions\><<< +static BOOL scan_until_end_str( ARG_IV(const C_CHAR *, int, BOOL, FILE *) ); +>>> + +\<functions\><<< +`[ +static BOOL scan_until_end_str(str,n,flag,file) + const C_CHAR *str`; + int n`; + BOOL flag`; + FILE* file +;{ Q_CHAR *p; + int i; + if( !flag ) { return flag; } + p = match[n]; i = 0; + while( TRUE ){ + if( (i+1) >= max_match[n] ){ + max_match[n] += 10; + p = match[n] = (Q_CHAR *) + r_alloc((void *) match[n], (size_t) max_match[n]); + } + p[i] = (char) (eoln_ch = getc(file)); + if( (eoln_ch == (int) '\n') || (eoln_ch == EOF) ){ break; } + i++; + } + p[i] = '\0'; + i -= (int) strlen(str); + if( i>= 0 ){ return eq_str(p+i,str); } + return FALSE; +} +>>> + + + +\<vars\><<< +static Q_CHAR* match[10]; +static int max_match[10]; +>>> + + +\<main's init\><<< +{ int i; + for( i=0; i<=9; i++){ + match[i] = (Q_CHAR *) malloc(70); + max_match[i] = 70; + } +} +>>> + + +\<header functions\><<< +static BOOL scan_until_str( ARG_IV(const C_CHAR *, int, BOOL, FILE *) ); +>>> + +\<functions\><<< +`[ +static BOOL scan_until_str(str,n,flag,file) + const C_CHAR *str`; + int n`; + BOOL flag`; + FILE* file +;{ Q_CHAR *p, ch; + int i, j; + if( !flag ) { return flag; } + p = match[n]; i = 0; + while( TRUE ){ + ch = (char) (eoln_ch = getc(file)); + if( (eoln_ch == (int) '\n') || (eoln_ch == EOF) ){ return FALSE; } + if( (i+1) >= max_match[n] ){ + max_match[n] += 10; + p = match[n] = (Q_CHAR *) + r_alloc((void *) match[n], (size_t) max_match[n]); + } + p[i++] = ch; + j = i - (int) strlen(str); + if( j>= 0 ){ + p[i] = '\0'; + if( eq_str(p+j,str) ) { return TRUE; } + } + } +} +>>> + + + + + + +\<header functions\><<< +static BOOL scan_str( ARG_III(const C_CHAR *, BOOL, FILE *) ); +>>> + +\<functions\><<< +`[ +static BOOL scan_str(str,flag,file) + const C_CHAR *str`; + BOOL flag`; + FILE* file +;{ const Q_CHAR *p; + int temp_eoln_ch; + if( !flag ) { return flag; } + p = str; + while( *p != '\0' ){ + if( *(p++) != (temp_eoln_ch = getc(file)) ) { + while( (temp_eoln_ch != (int) '\n') + && (temp_eoln_ch != EOF) ){ temp_eoln_ch = getc(file); } + eoln_ch = temp_eoln_ch; return FALSE; + } + } + return TRUE; +} +>>> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +\SubSection{Shorthands and Mnemonics} + + + +\<defines\><<< +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef BOOL +#define BOOL int +#endif +>>> + + + +\<defines\><<< +#define eq_str(x,y) (!strcmp(x,y)) +>>> + + + +%---------------------------------------------------- + +\OutputCodE\<t4ht.c\> + +\bye + + + |