File: rsc.c

package info (click to toggle)
bibtool 2.67%2Bds-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 2,608 kB
  • sloc: ansic: 11,646; perl: 7,482; makefile: 543; sh: 301; tcl: 51
file content (342 lines) | stat: -rw-r--r-- 14,064 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
/*** rsc.c ********************************************************************
** 
** This file is part of BibTool.
** It is distributed under the GNU General Public License.
** See the file COPYING for details.
** 
** (c) 1996-2017 Gerd Neugebauer
** 
** Net: gene@gerd-neugebauer.de
** 
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2, or (at your option)
** any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**-----------------------------------------------------------------------------
** Description:
**	This module contains functions which deal with resources.
**	Resources are commands to configure the behaviour of
**	\BibTool. They can be read either from a file or from a
**	string. 
**
**	The syntax of resources are modelled after the syntax rules
**	for \BibTeX{} files. See the user's guide for details of the syntax.
**
******************************************************************************/

#include <bibtool/general.h>
#include <bibtool/error.h>
#include <bibtool/symbols.h>
#include <bibtool/macros.h>
#include <bibtool/parse.h>
#include <bibtool/print.h>
#include <bibtool/tex_aux.h>
#include <bibtool/tex_read.h>
#include <bibtool/key.h>
#include <bibtool/rewrite.h>
#include <bibtool/s_parse.h>
#include <bibtool/entry.h>
#include <bibtool/type.h>
#include <bibtool/crossref.h>
#include <bibtool/version.h>
#include "config.h"
#define RSC_INIT
#include <bibtool/rsc.h>

/*****************************************************************************/
/* Internal Programs							     */
/*===========================================================================*/

#ifdef __STDC__
#define _ARG(A) A
#else
#define _ARG(A) ()
#endif
 static bool test_true _ARG((Symbol  s));	   /*                        */
 static void init_rsc _ARG((void));		   /*                        */

#define NoRscError(X)	      WARNING3("Resource file ",X," not found.")

/*****************************************************************************/
/* External Programs							     */
/*===========================================================================*/

 extern void save_input_file _ARG((char *file));   /* main.c		     */
 extern void save_macro_file _ARG((char * file));  /* main.c		     */
 extern void save_output_file _ARG((char * file)); /* main.c		     */

#ifndef __STDC__
#ifndef HAVE_GETENV
 extern char * getenv _ARG((char* name));	   /*			     */
#endif
#endif

/*---------------------------------------------------------------------------*/

#define RscNumeric(SYM,S,V,I) static Symbol S = NO_SYMBOL;
#define RscString(SYM,S,V,I)  static Symbol S = NO_SYMBOL;
#define RscBoolean(SYM,S,V,I) static Symbol S = NO_SYMBOL;
#define RscByFct(SYM,S,FCT)   static Symbol S = NO_SYMBOL;
#include <bibtool/resource.h>

/*-----------------------------------------------------------------------------
** Function:	init_rsc()
** Purpose:	This function performs resource initializations.  It
**		is necessary to call this function before the other
**		functions in this module can be expected to work
**		properly. Thus it is called at the beginning of the
**		functions is question.
** Details:
**		Initialize the key words.
**		Tricky use of CPP. The header file resource.h is included 
**		for the second time. To avoid confusion in makedepend the 
**		hader file is only included if MAKEDPEND is not defined.
**		The same trick can be found again later.
** Arguments:	none
** Returns:	nothing
**___________________________________________________			     */
static void init_rsc()				   /*			     */
{						   /*			     */
#define RscNumeric(SYM,S,V,I)  S = symbol((String)SYM);
#define RscString(SYM,S,V,I)   S = symbol((String)SYM);
#define RscBoolean(SYM,S,V,I)  S = symbol((String)SYM);
#define RscByFct(SYM,S,FCT)    S = symbol((String)SYM);
#ifndef MAKEDEPEND
#include <bibtool/resource.h>
#endif
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function:	search_rsc()
** Purpose:	Try to open the resource file at different places:
**		\begin{itemize}
**		\item In the place indicated by the environment variable
**		  |RSC_ENV_VAR|. This step is skipped if the macro
**		  |RSC_ENV_VAR| is not defined (at compile time of the
**		  module).
**		\item In the home directory.  The home directory is
**		  determined by an environment variable.  The macro
**		  |HOME_ENV_VAR| contains the name of this environment
**		  variable. If this macro is not defined (at
**		  compile time of the module) then this step is skipped.
**		\item In the usual place for resource files.
**		\end{itemize}
**		For each step |load_rsc()| is called until it
**		succeeds.
**
**		The files sought is determined by the macro
**		|DefaultResourceFile| at compile time of the
**		module. (see |bibtool.h|)
** Arguments:	none
** Returns:	|true| iff the resource loading succeeds somewhere.
**___________________________________________________			     */
bool search_rsc()				   /*			     */
{ static String	def = (String)DefaultResourceFile; /*			     */
  register char *ap;				   /*			     */
  register char *fn;				   /*			     */
  size_t	len;			   	   /*			     */
  bool		found;
						   /*			     */
#ifdef RSC_ENV_VAR
  if ( (ap=getenv(RSC_ENV_VAR)) != NULL		   /* Try to get the name    */
       && load_rsc((String)ap) ) return true;	   /*  from the environment. */
#endif
						   /*			     */
#ifdef HOME_ENV_VAR
  if ( (ap=getenv(HOME_ENV_VAR)) != NULL )	   /* Try to get the resource*/
  { len = strlen(ap) +				   /*                        */
          strlen(DIR_SEP) +			   /*                        */
          strlen((char*)def) + 1;		   /*  file from the home    */
    if ((fn=malloc(len)) != NULL)		   /*  directory	     */
    { (void)strcpy(fn, ap);			   /*			     */
      (void)strcat(fn, DIR_SEP);		   /*			     */
      (void)strcat(fn, (char*)def);		   /*			     */
      found = load_rsc((String)fn);		   /*			     */
      free(fn);					   /*			     */
      if (found) return true;			   /*			     */
    }						   /*			     */
  }						   /*			     */
#endif
						   /* if all fails then try  */
  return load_rsc(def);				   /*  to use a default.     */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function:	load_rsc()
** Purpose:	This function tries to load a resource file. 
** Details:
** 		Perform initialization if required.
** 		The main job is done by |read_rsc()|. This function is located
** 		in |parse.c| since it shares subroutines with the parser.
** Arguments:
**	name	The name of the resource file to read.
** Returns:	|false| iff the reading failed.
**___________________________________________________			     */
bool load_rsc(name)			   	   /*			     */
  register String name;				   /*			     */
{						   /*			     */
  if (r_v == NULL) { init_rsc(); }		   /*			     */
  return (name != NULL ? read_rsc(name) : false);  /*			     */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function:	resource()
** Type:	int
** Purpose:	
**		
** Arguments:
**	name	the name of the resource file
** Returns:	
**___________________________________________________			     */
bool resource(name)			   	   /*			     */
  register String name;				   /*			     */
{						   /*			     */
  bool ret = load_rsc(name);			   /*                        */
  if (!ret) { NoRscError(name); }		   /*                        */
  return ret;	   				   /*			     */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function*:	test_true()
** Purpose:	A boolean resource can be set to true in different ways:
**		|true|, |t|, |yes|, |on|, |1|
**		which represent ``true''.  Each other value is
**		interpreted as ``false''. 
**		The comparison is done case insensitive.
** Arguments:
**	sym	String to check for the boolean value.
** Returns:	|true| iff the string represents true.
**___________________________________________________			     */
static bool test_true(sym)			   /*			     */
  Symbol sym;				   	   /*			     */
{ register String s = SymbolValue(sym);		   /*                        */
						   /*			     */
  switch ( *s )					   /*                        */
  { case '1':		return (s[1] == '\0');	   /*                        */
    case 'o': case 'O':				   /*                        */
      return ((s[1] == 'n' || s[1] == 'N') &&	   /*                        */
	      s[2] == '\0' );			   /*                        */
    case 'y': case 'Y':				   /*                        */
      return ((s[1] == 'e' || s[1] == 'E') &&	   /*                        */
	      (s[2] == 's' || s[2] == 'S') &&	   /*                        */
	      s[3] == '\0' );			   /*                        */
    case 't': case 'T':				   /*                        */
      return (s[1] == '\0' ||			   /*                        */
	      ((s[1] == 'r' || s[1] == 'R') &&	   /*                        */
	       (s[2] == 'u' || s[2] == 'U') &&	   /*                        */
	       (s[3] == 'e' || s[3] == 'E') &&	   /*                        */
	       s[4] == '\0'));			   /*                        */
  }						   /*                        */
  return false;					   /*                        */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function:	use_rsc()
** Purpose:	This function can be used to evaluate a single
**		resource instruction. The argument is a string which
**		is parsed to extract the resource command.
**
**		This is an entry point for command line options which
**		set resources. 
** Arguments:
**	s	String containing a resource command.
** Returns:	|true| iff an error has occurred.
**___________________________________________________			     */
bool use_rsc(s)					   /*			     */
  String	  s;				   /*			     */
{ register Symbol name,				   /*			     */
		  value;			   /*			     */
						   /*			     */
  sp_open(s);				   	   /*			     */
  if ((name = SParseSymbol(&s)) == NULL) return true;/*			     */
						   /*			     */
  sp_skip(&s);				   	   /*                        */
						   /*			     */
  if ((value = SParseValue(&s)) == NULL)	   /*                        */
  { UnlinkSymbol(name);			   	   /*                        */
    return true;				   /*			     */
  }						   /*                        */
						   /*			     */
  if (r_v == NULL) { init_rsc(); }		   /*			     */
						   /*			     */
  return set_rsc(name, value);			   /*                        */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function:	set_rsc()
** Purpose:	Set the resource to a given value. Here the assignment
**		is divided into two parts: the name and the value.
**		Both arguments are assumed to be symbols.
** Arguments:
**	name	Name of the resource to set.
**	val	The new value of the resource.
** Returns:	|false| iff everything went right.
**___________________________________________________			     */
bool set_rsc(name,val)				   /*			     */
  Symbol name;				   	   /*			     */
  Symbol val;				   	   /*			     */
{						   /*			     */
  if ( rsc_verbose )				   /*			     */
  { VerbosePrint4("Set resource ",		   /*                        */
		  (char*)SymbolValue(name),	   /*                        */
		  " = ",			   /*                        */
		  ( val == NO_SYMBOL		   /*                        */
		    ? "*NULL*"			   /*                        */
		    : (char*)SymbolValue(val)));   /*	                     */
  }						   /*                        */
						   /*			     */
#define SETQ(V,T) V=T; UnlinkSymbol(name);
#define RscNumeric(SYM,S,V,I)						\
  if ( name == S ) { SETQ(V,atoi((char*)SymbolValue(val)));		\
    UnlinkSymbol(val); return false; }
#define RscString(SYM,S,V,I)						\
  if ( name == S ) { V = (String)new_string((char*)SymbolValue(val));	\
    UnlinkSymbol(name); return false; }
#define RscBoolean(SYM,S,V,I)						\
  if ( name == S ) { SETQ(V,test_true(val));				\
    UnlinkSymbol(val); return false; }
#define RscByFct(SYM,S,FCT)						\
  if ( name == S ) { (void)FCT;						\
    UnlinkSymbol(name); return false; }
#define RSC_FIRST(C)	      case C:
#define RSC_NEXT(C)	      break; case C:
						   /*			     */
  switch (*SymbolValue(name))			   /*			     */
  {						   /*			     */
#ifndef MAKEDEPEND
#include <bibtool/resource.h>
#endif
  }						   /*			     */
						   /*			     */
  ERROR3("Resource ", SymbolValue(name),	   /*                        */
	 " unknown.");				   /*			     */
  UnlinkSymbol(name);				   /*                        */
  UnlinkSymbol(val);				   /*                        */
  return 1;					   /*			     */
}						   /*------------------------*/

/*-----------------------------------------------------------------------------
** Function:	rsc_print()
** Purpose:	Print a string to the error stream as defined in
**		|error.h|. The string is automatically augmented by a
**		trailing newline.
**		This wrapper function is used for the resource |print|.
** Arguments:
**	s	String to print.
** Returns:	nothing
**___________________________________________________			     */
void rsc_print(s)				   /*			     */
  String s;				   	   /*			     */
{ ErrPrintF("%s\n", (char*)s);			   /* print the string itself*/
			   			   /* followed by a newline  */
}						   /*------------------------*/