2
* ChkTeX, operating system specific code for ChkTeX.
3
* Copyright (C) 1995-96 Jens T. Berger Thielemann
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
* Contact the author at:
24
* E-mail: <jensthi@ifi.uio.no>
31
* Some functions which have to be made different from OS to OS,
40
#ifdef HAVE_SYS_STAT_H
41
# include <sys/stat.h>
49
# define NAMLEN(dirent) strlen((dirent)->d_name)
51
# define dirent direct
52
# define NAMLEN(dirent) (dirent)->d_namlen
54
# include <sys/ndir.h>
64
#if defined(HAVE_OPENDIR) && defined(HAVE_CLOSEDIR) && \
65
defined(HAVE_READDIR) && defined(HAVE_STAT) && \
66
defined(S_IFDIR) && defined(SLASH)
67
# define USE_RECURSE 1
69
# define USE_RECURSE 0
72
#if defined(HAVE_LIBTERMCAP) || defined(HAVE_LIBTERMLIB)
73
# define USE_TERMCAP 1
78
# ifdef HAVE_TERMCAP_H
83
int tgetent(char *BUFFER, char *TERMTYPE);
84
char *tgetstr(char *NAME, char **AREA);
86
static char term_buffer[2048];
89
/* -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- */
92
* This is the name of the global resource file.
96
# if defined(__unix__)
97
# define SYSCONFDIR "/usr/local/lib/"
98
# elif defined(__MSDOS__)
99
# define SYSCONFDIR "\\emtex\\data\\"
104
#define RCBASENAME "chktexrc"
107
# define LOCALRCFILE RCBASENAME
109
# define LOCALRCFILE "." RCBASENAME
112
char ConfigFile[BUFSIZ] = LOCALRCFILE;
113
const char *ReverseOn;
114
const char *ReverseOff;
117
static int HasFile(char *Dir, const char *Filename, const char *App);
120
static int SearchFile(char *Dir, const char *Filename, const char *App);
121
#endif /* USE_RECURSE */
123
/* -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- */
127
* Modify this one to suit your needs. In any case, it should fill
128
* the ConfigFile (sized BUFLEN) buffer above with full name & path
129
* for the configuration file. The macro RCFILE will give you the
130
* filename part of the file, if you need that.
132
* Note: This routine will be called several times. Your mission will
133
* be to look in each location, and see whether a .chktexrc file exist
136
* If you choose to do nothing, only the current directory will be
162
static enum LookIn i = liMin;
163
static int FoundFile;
169
case liCurDir: /* Current directory */
170
strcpy(ConfigFile, LOCALRCFILE);
172
case liEnvir: /* Environment defined */
175
if ((Env = getenv("CHKTEXRC")) || (Env = getenv("CHKTEX_HOME")))
178
if ((Env = getenv("CHKTEXRC")))
182
strcpy(ConfigFile, Env);
183
tackon(ConfigFile, LOCALRCFILE);
187
if ((Env = getenv("EMTEXDIR")))
189
strcpy(ConfigFile, Env);
190
tackon(ConfigFile, "data");
191
tackon(ConfigFile, LOCALRCFILE);
198
case liUsrDir: /* User dir for resource files */
199
#if defined(__unix__)
201
if ((Env = getenv("HOME")) || (Env = getenv("LOGDIR")))
203
strcpy(ConfigFile, Env);
204
tackon(ConfigFile, LOCALRCFILE);
207
#elif defined(__MSDOS__)
209
strcpy(ConfigFile, PrgName);
210
if ((Ptr = strrchr(ConfigFile, '\\')) ||
211
(Ptr = strchr(ConfigFile, ':')))
212
strcpy(++Ptr, RCBASENAME);
218
case liSysDir: /* System dir for resource files */
220
if ((Env = getenv("CHKTEX_CONFIG")))
222
strcpy(ConfigFile, Env);
228
if ((f = popen("kpsewhich -expand-var='$TEXMFMAIN'", "r")))
230
if (1 == fscanf(f, "%1024s", ConfigFile))
232
tackon(ConfigFile, "chktex");
233
tackon(ConfigFile, RCBASENAME);
239
#if defined(__unix__) || defined(__MSDOS__)
240
strcpy(ConfigFile, SYSCONFDIR);
241
tackon(ConfigFile, RCBASENAME);
245
#endif /* TEX_LIVE */
253
PrintPrgErr(pmNoRsrc);
256
if (*ConfigFile && fexists(ConfigFile))
259
FoundFile |= *ConfigFile;
261
return (*ConfigFile);
265
/* -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- */
268
* This function should initialize the global variables ReverseOn
269
* and ReverseOff to magic cookies, which when printed, makes the
270
* text in between stand out.
276
char *termtype = getenv("TERM");
279
static char str_so[3] = "so", str_se[3] = "se";
284
success = tgetent(term_buffer, termtype);
286
PrintPrgErr(pmNoTermData);
288
PrintPrgErr(pmNoTermDefd);
290
buffer = (char *) malloc(sizeof(term_buffer));
291
ReverseOn = tgetstr(str_so, &buffer);
292
ReverseOff = tgetstr(str_se, &buffer);
294
if (ReverseOn && ReverseOff)
299
ReverseOn = PRE_ERROR_STR;
300
ReverseOff = POST_ERROR_STR;
303
/* -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- */
306
* Concatenates the `File' string to the `Dir' string, leaving the result
307
* in the `Dir' buffer. Takes care of inserting `directory' characters;
308
* if we've got the strings "/usr/foo" and "bar", we'll get
311
* Behaviour somewhat controlled by the macros SLASH and DIRCHARS in the
316
void tackon(char *Dir, const char *File)
321
if (Dir && (SLen = strlen(Dir)))
323
EndC = Dir[SLen - 1];
324
if (!(strchr(DIRCHARS, EndC)))
335
* This function should add the appendix App to the filename Name.
336
* If the resulting filename gets too long due to this, it may
337
* overwrite the old appendix.
339
* Name may be assumed to be a legal filename under your OS.
341
* The appendix should contain a leading dot.
344
void AddAppendix(char *Name, const char *App)
349
if ((p = strrchr(Name, '.')))
355
* NOTE! This may fail if your system has a claustrophobic file
363
/* -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- */
367
* Locates a file, given a wordlist containing paths. If a
368
* dir ends in a double SLASH, we'll search it recursively.
371
* a) a deeper level in the dir. tree. has a longer path than
373
* b) adding a level doesn't change any of the previous levels.
375
* If this function returns TRUE, Dest is guaranteed to contain
376
* path & name of the found file.
378
* FALSE indicates that the file was not found; Dest is then
383
int LocateFile(const char *Filename, /* File to search for */
384
char *Dest, /* Where to put final file */
385
const char *App, /* Extra optional appendix */
386
struct WordList *wl) /* List of paths, entries
387
* ending in // will be recursed
398
strcpy(Dest, wl->Stack.Data[i]);
404
if (Len && (Dest[Len - 1] == SLASH) && (Dest[Len - 2] == SLASH))
406
Dest[Len - 1] = Dest[Len - 2] = 0;
407
if (SearchFile(Dest, Filename, App))
411
#endif /* USE_RECURSE */
414
if (HasFile(Dest, Filename, App))
421
static int HasFile(char *Dir, const char *Filename, const char *App)
423
int DirLen = strlen(Dir);
425
tackon(Dir, Filename);
431
AddAppendix(Dir, App);
443
static int SearchFile(char *Dir, const char *Filename, const char *App)
445
struct stat *statbuf;
449
int DirLen = strlen(Dir);
452
DEBUG(("Searching %s for %s\n", Dir, Filename));
454
if (HasFile(Dir, Filename, App))
458
if ((statbuf = malloc(sizeof(struct stat))))
460
if ((dh = opendir(Dir)))
462
while (!Found && (de = readdir(dh)))
465
if (strcmp(de->d_name, ".") && strcmp(de->d_name, ".."))
467
tackon(Dir, de->d_name);
469
if (!stat(Dir, statbuf))
471
if ((statbuf->st_mode & S_IFMT) == S_IFDIR)
472
Found = SearchFile(Dir, Filename, App);
479
PrintPrgErr(pmNoOpenDir, Dir);
485
#endif /* USE_RECURSE */