#ifndef lint
#ifdef standalone_lgutil
static char sccsid[] = "@(#)lgutil.c 3.6 (MPi) 24/3/98";
static char rcsid[] =
"$Id: lgutil.c,v 1.7 1999/12/18 21:54:29 mike Exp $";
#endif /* standalone_lgutil */
#endif
/* lgutil.c
* Utility Functions for LGrind
* This file is @#include@d from lgrind.c (likely to change)
*/
/* Copyright %%\copyright%% 1998,1999 Michael Piefel
*
* This file is something like GPL, though LGrind is BSD.
* I don't want to become a lawyer.
*/
/*
* Internal_Help() --- show help
*/
void Internal_Help()
{
printf("lgrind -- general purpose \"pretty printer\" for use with LaTeX.\n");
printf("usage: lgrind [options] <name> ...\n");
printf("-e process embedded text in a LaTeX file\n");
printf("-i format source code for inclusion in a LaTeX document.\n");
printf("-n don't boldface keywords.\n");
printf("-a don't treat @, etc. specially in LaTeX.\n");
printf("-c don't treat @, etc. specially in comments.\n");
printf("- take input from standard input.\n");
printf("-o <file> write to file (instead of standard output).\n");
printf("-t <width> change tab width (default 8).\n");
printf("-h <header> specifies text in header (default: none).\n");
printf("-v <varfile> take variable substitutions from file.\n");
printf("-d <deffile> use a different language definitions file, default:\
\n \"%s\"\n", defsfile);
printf("-l<language> choose the language to use.\n");
printf("-s show a list of currently known languages.\n\n");
printf("If neither -e nor -i are specified, a complete LaTeX-file is produced.\n\n");
printf("Direct comments and questions to
[email protected]\n");
}
typedef struct langRec {
char *name;
char *alternatives;
struct langRec *next; } langRec;
void AddToLList(char *line, langRec **into, int *chainLength)
{
char *token, *item, *alts;
if (*line!='#' && *line!='\n')
{
item=strdup(line);
if ((token=strtok(item, "|:\\\n")) == NULL) return;
(**into).next=(langRec*)malloc(sizeof(langRec));
*into=(**into).next;
(**into).name=strdup(token);
(*chainLength)++;
if ((token=strtok(NULL, "|:\\\n")) == NULL)
{
(**into).alternatives="\0";
return;
}
(**into).alternatives=strdup(token);
while ((token=strtok(NULL, "|:\\\n")) != NULL)
{
alts=(**into).alternatives;
(**into).alternatives=(char*)malloc(
strlen((**into).alternatives)+strlen(token)+1);
/* This is extremely poor style and dangerous. I leave memory
* allocated here because after invocation of this help facility
* the program will stop anyway. In this context it is safe. */
strcpy((**into).alternatives, alts);
strcat((**into).alternatives, ", ");
strcat((**into).alternatives, token);
}
}
}
void Internal_Help_Language_List()
{
FILE *tf;
int check, i, llch;
langRec *lch, *rch, *currlch;
/* @lch2@ was originally "language chain", but I guess
it's "left" as well */
printf("When specifying a language case is insignificant. You can use the\n");
printf("name of the language, or, where available, one of the synonyms in\n");
printf("parantheses. Thus the following are legal and mark Tcl/Tk, Pascal\n");
printf("and Fortran input, respectively:\n");
printf(" lgrind -ltcl/tk ...\n");
printf(" lgrind -lpaSCAL ...\n");
printf(" lgrind -lf ...\n");
printf("The list of languages currently available in your lgrindef file:\n");
tf = fopen(defsfile, "rt");
if (tf == NULL)
{
fprintf(stderr, "cannot find lgrindef file `%s'\n", defsfile);
return;
}
llch=0;
currlch=lch=(langRec*)malloc(sizeof(langRec));
(*currlch).name="";
*config='\n';
do {
check=0;
if (*config=='\n' || config[strlen(config)-2]!='\\')
check=1;
if (fgets(config, BUFFERSIZE, tf)==NULL) break;
if (check!=0) AddToLList(config, &currlch, &llch);
} while (strcmp((*currlch).name, "EndOfLanguageDefinitions")!=0);
rch=lch;
for (check=0; check<llch/2; check++)
rch=(*rch).next;
for (check=0; check<llch/2; check++)
{
lch=(*lch).next;
rch=(*rch).next;
printf(" %s", (*lch).name);
if (*((*lch).alternatives)) printf(" (%s)", (*lch).alternatives);
else printf(" ");
for (i=strlen((*lch).name)+strlen((*lch).alternatives);
i<30; i++) putchar(' ');
if (rch!=currlch)
{
printf("%s", (*rch).name);
if (*((*rch).alternatives)) printf(" (%s)", (*rch).alternatives);
}
printf("\n");
}
}
/*
* Redefine Chartab from lgrindef file
*/
void parsechartab(void)
{
char *i=buf, *j=chartab, c;
int charnum=0;
while (*i++!=':') {}
while ((c=*i++)!='\0') {
if (c==':') continue;
charnum=(c>='0' && c<='9') ? (int)c-48 : tolower(c)-87;
charnum=charnum << 4; c=*i++;
charnum+=(c>='0' && c<='9') ? (int)c-48 : tolower(c)-87;
i++;
printtab[charnum]=j;
while (*i!=':')
if (*i=='\\') {
switch (*++i) {
case ':': *j++=':'; break;
case '\\': *j++='\\'; break;
}; i++;
} else *j++=*i++;
*j++='\0';
}
}
/*
* Parses the %|lgrindef|% file for a preamble
*/
void parsepreamble(char *destination)
{
char *i=buf, *j=destination;
while (*i++!=':') ;
while (*i) {
if (*i=='\\') {
switch (*++i) {
case 'n': *j++='\n'; break;
case 't': *j++='\t'; break;
case 'f': *j++='\f'; break;
case '\\': *j++='\\'; break;
default: fprintf(stderr, "Bad preamble entry: incorrect '\\'\n");
}; i++;
} else *j++=*i++;
*j='\0';
}
}
/*
* Sets the default preambles
*/
void setpreambles(void)
{
strcpy(preamble,
"\\documentclass[a4paper]{article}\n\
\\usepackage[procnames,noindent]{lgrind}\n\
\\usepackage{fancyhdr}\n\
\\pagestyle{fancy}\n\
\\begin{document}\n");
strcpy(postamble, "\\end{document}\n");
strcpy(preamble2,
"\\lhead[\\fancyplain{}{\\bf\\thepage}]\
{\\fancyplain{}{\\bf \f}}\n\
\\rhead[\\fancyplain{}{\\bf \f}]\
{\\fancyplain{}{\\bf\\thepage}}\n\
\\cfoot{}\n");
strcpy(config, "");
}
/*
* prints a preamble, substituting %|\f|% with the current
* file's name (sorry, no more form feeds)
*/
void printpreamble(char *string)
{
char *i;
while (*string)
if (*string=='\f')
{ i=fname-1;
while (*(++i)) outchar(*i);
string++;
}
else putchar(*string++);
}
/*
* try to create an executable file to store the new lgrindef-file
*/
void writeDefsfileInExe(char *progname, char *newdefsfile)
{
char *buffer, *i;
FILE *progfile, *newfile;
long pos=0;
int ret;
buffer = (char*) malloc(30000);
/* So small? Why in chunks? Well, it's gotta run on machines with
only limited access to their resources (you know, the IBM PC) */
progfile=fopen(progname, "rb");
newfile=fopen("lgrind.new", "wb");
if (buffer && progfile && newfile)
{
fread(buffer, 1, 200, progfile);
do {
ret=fread(buffer+200, 1, 29500, progfile);
for(i=buffer; i<buffer+ret; i++)
if (*i=='D' &&
*(i+1)=='e' &&
*(i+2)=='F' &&
*(i+3)=='s' &&
*(i+4)=='B' &&
*(i+5)=='u' &&
*(i+6)=='F' &&
strcmp(defsfile, i+7)==0) {
memcpy(i+7, newdefsfile, strlen(newdefsfile)+1);
}
fwrite(buffer, 1, ret==29500 ? ret : ret+200, newfile);
memcpy(buffer, buffer+29500, 200);
pos+=29500;
} while (ret==29500);
fclose(progfile);
fclose(newfile);
}
free(buffer);
}
/*
* Reads a variable substitution table from a file
*/
varsubst *parsevartab(char* fname)
{
FILE *f = fopen(fname, "rt");
char linebuf[201], *cp;
varsubst *varsubsts=NULL, *substitem, *substlistpos;
if (f==NULL) return;
while (!feof(f))
{
fscanf(f, "%200[^\n]", linebuf);
fscanf(f, "\n");
cp=strchr(linebuf, '=');
if (cp==NULL) continue;
*cp++='\0';
substitem=(varsubst*)malloc(sizeof(varsubst));
substitem->var=strdup(linebuf);
substitem->subst=strdup(cp);
substitem->next=NULL;
if (varsubsts==NULL)
{
varsubsts=substitem;
substlistpos=substitem;
} else {
substlistpos->next=substitem;
substlistpos=substitem;
}
}
fclose(f);
return varsubsts;
}
/*
* Replaces a variable by alternate representation
*/
int substvarname(char **ident, int i)
{
varsubst *substlistpos = varsubstlist;
while (substlistpos!=NULL)
{
if (re_strncmp(*ident, substlistpos->var, i)==0)
{
*ident+=i; /* skip i characters in input */
printf("%s", substlistpos->subst);
return 0;
}
substlistpos=substlistpos->next;
}
return i;
}