1
/* Copyright (C) 1995 Bjoern Beutel. */
3
/* Description. =============================================================*/
5
/* This file contains basic types, macros and functions used everywhere. */
7
/* Constants. ===============================================================*/
10
#define NULL 0 /* Null pointer. */
12
enum {BITS_PER_BYTE = 8};
14
/* Attribute for a function that never returns. */
16
#define NO_RETURN __attribute__((noreturn))
21
/* Basic types. =============================================================*/
24
typedef signed char byte_t; /* Signed 8 bits. */
25
typedef unsigned char u_byte_t; /* Unsigned 8 bits. */
26
typedef signed short short_t; /* Signed 16 bits. */
27
typedef unsigned short u_short_t; /* Unsigned 16 bits. */
28
typedef signed int int_t; /* Signed 32 bits. */
29
typedef unsigned int u_int_t; /* Unsigned 32 bits. */
30
typedef unsigned long ptr_t; /* Pointer in arithmetic expressions. */
32
/* Character types. */
33
typedef char char_t; /* A single char. */
34
typedef char_t *string_t; /* An EOS-terminated C string. */
35
enum {EOS= '\0'}; /* End-Of-String control character. */
36
#define ORD(c) ((u_byte_t) (c)) /* The ordinal number of character C. */
39
#undef bool_t /* <rpc/rpc.h> conflicts with "bool_t" definition. */
42
typedef enum {FALSE, TRUE} bool_t;
44
/* Macros. ==================================================================*/
47
#define MIN(a,b) ((a) < (b) ? (a) : (b)) /* Minimum of A and B. */
49
#define MAX(a,b) ((a) > (b) ? (a) : (b)) /* Maximum of A and B. */
51
#define ABS(a) ((a) >= 0 ? (a) : (-a)) /* Absolute value of A. */
53
#define IS_ALPHA(c) ((hangul && ORD(c) > 127) || isalpha( ORD(c) ))
54
#define IS_PRINT(c) ((hangul && ORD(c) > 127) || isprint( ORD(c) ))
55
#define IS_DIGIT(c) isdigit( ORD(c) )
56
#define IS_SPACE(c) isspace( ORD(c) )
57
#define TO_LOWER(c) ((hangul && ORD(c) > 127) \
58
? (char_t) (c) : (char_t) tolower( ORD(c) ))
60
/* Global variables. ========================================================*/
62
extern bool_t user_break_requested;
63
/* Flag that indicates that user has send a Ctrl-C. */
65
/* Read-only variables. =====================================================*/
67
extern char_t malaga_version[];
68
extern string_t program_name; /* This is set by "init_basic". */
69
extern bool_t in_emacs_malaga_mode; /* This is set by "init_basic". */
70
extern bool_t hangul; /* This is set by "init_basic". */
72
/* Program message. =========================================================*/
74
extern void program_message( void );
75
/* Print some information about the program. */
77
/* Forward-linked lists. ====================================================*/
79
typedef struct list_node /* A node in a list of nodes. */
81
struct list_node *next; /* Next list node. */
84
typedef struct /* A list of nodes. */
86
list_node_t *first, *last; /* The first and last element in the list. */
89
typedef enum {LIST_START, LIST_END} position_t;
90
/* The position where a new element is added to a list. */
92
extern void clear_list( list_t *list );
93
/* Initialise LIST to be an empty list */
95
extern void add_node( list_t *list, list_node_t *node, position_t position );
97
* If POSITION = LIST_START, add it at the start of the list;
98
* If POSITION = LIST_END, add it at the end. */
100
extern void insert_node( list_t *list, list_node_t *node, list_node_t *prev );
101
/* Insert NODE in LIST, behind PREV.
102
* If PREV == NULL, insert NODE at the beginning of the list. */
104
extern void *remove_first_node( list_t *list );
105
/* Remove the first node in LIST and return it. */
107
extern void remove_node( list_t *list, list_node_t *node );
108
/* Remove NODE in LIST. */
110
extern void combine_lists( list_t *list1, list_t *list2 );
111
/* Append LIST2 to LIST1.
112
* LIST1 will contain the concatenation; LIST2 will be empty. */
114
extern void *new_node( list_t *list, int_t size, position_t position );
115
/* Add a node of size SIZE to LIST.
116
* If POSITION = LIST_START, add the element at the start of the list;
117
* If POSITION = LIST_END, add the element at the end.
118
* Return the newly created node. */
120
extern void free_first_node( list_t *list );
121
/* Remove first node in LIST and free it. */
123
extern void free_node( list_t *list, list_node_t *node );
124
/* Remove NODE from LIST and free it. */
126
/* Iterate through a "list_t". */
127
#define FOREACH(var, list) \
128
for ((var) = (void *) (list).first; \
130
(var) = (void *) (var)->next)
132
/* Iterate through a "list_t" and free every node in it. */
133
#define FOREACH_FREE(var, list) \
134
for ((var) = (void *) (list).first; \
136
(var) = (void *) (var)->next, free_first_node( &(list) ))
138
/* Memory functions. ========================================================*/
140
extern void *new_mem( int_t item_size );
141
/* Allocate a memory block of ITEM_SIZE bytes, clear it and return it.
142
* If memory is out, call the function "error". */
144
extern void *new_vector( int_t item_size, int_t item_count );
145
/* Allocate a memory block to contain ITEM_COUNT items of size ITEM_SIZE,
146
* clear it and return it.
147
* If memory is out, call the function "error". */
149
extern int_t renew_vector( void *block_p, int_t item_size, int_t item_count );
150
/* Realloc *BLOCK_P to contain ITEM_COUNT items of ITEM_SIZE bytes each.
152
* If memory is out, call the function "error". */
154
extern void free_mem( void *pointer );
155
/* Free memory *POINTER points to, and set *POINTER to NULL. */
157
/* String functions. ========================================================*/
159
extern string_t new_string( string_t string, string_t end );
160
/* Allocate memory and copy STRING into it.
161
* If END != NULL, it marks the end of the string.
162
* The result string must be freed after use. */
164
extern string_t new_string_readable( string_t from, string_t from_end );
165
/* Like "new_string", but copy a "\" in front of quotes
166
* and copy any control chars in octal code: "\000".
167
* If FROM_END != NULL, it marks the end of the string.
168
* The result string must be freed after use. */
170
extern string_t concat_strings( string_t first_string, ... );
171
/* Concatenate a list of strings and return the result string.
172
* Must have NULL-terminated list of strings as parameters.
173
* The result string must be freed after use. */
175
extern int_t strcmp_no_case( string_t str1, string_t str2 );
176
/* Return (case insensitive) lexical order of STR1 and STR2:
177
* Result is -1 if STR1 < STR2,
179
* 1 if STR1 > STR2. */
181
extern int_t strncmp_no_case( string_t str1, string_t str2, int_t n );
182
/* Return (case insensitive) lexical order of STR1 and STR2,
183
* but compare only the first N characters.
184
* Result is -1 if STR1 < STR2,
186
* 1 if STR1 > STR2. */
188
extern string_t next_non_space( string_t string );
189
/* Return STRING, but without leading spaces. */
191
extern string_t double_to_string( double number );
192
/* Convert NUMBER to a string. The string must be freed after use. */
194
extern string_t int_to_string( int_t number );
195
/* Convert NUMBER to a string. The string must be freed after use. */
197
extern string_t replace_arguments( string_t format, string_t chars, ... );
198
/* Create a new string with a copy of FORMAT.
199
* Replace each sequence "%C" in FORMAT, where C is the N-th
200
* char in CHARS, by the N-th additional string argument.
201
* The result string must be freed after use. */
203
/* Text functions. ==========================================================*/
205
/* A data structure that contains a string that may grow indefinitely. */
213
extern text_t *new_text( void );
214
/* Return a new text structure. */
216
extern void clear_text( text_t *text );
217
/* Initialize TEXT to an empty string. */
219
extern void free_text( text_t **text_p );
220
/* Free the content of *TEXT_P. */
222
extern void add_to_text( text_t *text, string_t string );
223
/* Add STRING to TEXT. */
225
extern void add_char_to_text( text_t *text, char_t character );
226
/* Add CHARACTER to TEXT. */
228
extern void insert_in_text( text_t *text, string_t string, int_t position );
229
/* Insert STRING at POSITION in TEXT (position counts from 0 onward). */
231
extern void insert_char_in_text( text_t *text,
234
/* Insert CHARACTER at POSITION in TEXT. */
236
extern void print_text( text_t *text, string_t format, ... );
237
/* Add FORMAT to TEXT, replace any "%s" with a "string_t" argument,
238
* and any "%d" with an "int_t" argument. */
240
extern string_t text_to_string( text_t **text_p );
241
/* Return content of *TEXT_P as a string and delete *TEXT_P.
242
* The string must be freed after use. */
244
/* Add CHARACTER to TEXT (macro version). */
245
#define ADD_CHAR_TO_TEXT( text, character ) \
247
if (text->buffer_size < text->string_size + 2) \
249
text->buffer_size = renew_vector( &text->buffer, sizeof( char_t ), \
250
2 * (text->string_size + 1) ); \
252
text->buffer[ text->string_size++ ] = character; \
253
text->buffer[ text->string_size ] = EOS; \
256
/* Error handlers. ==========================================================*/
258
/* The syntax of an error handler is:
260
* IF_ERROR STATEMENT2
264
* The parts "IF_ERROR STATEMENT2" and "FINALLY STATEMENT3" are optional.
266
* First, STATEMENT1 is executed.
267
* If the function "error" is called in STATEMENT1 or in a function
268
* called from there, STATEMENT2 and then STATEMENT3 will be executed
270
* If the function "error" is not called, STATEMENT3 will executed.
271
* In STATEMENT2, you can use the statement "RESUME" to leave the error
276
jmp_buf _handler, *_older_handler = _error_handler; \
277
volatile bool_t _rethrow; \
278
_error_handler = &_handler; \
279
if (! (_rethrow = setjmp( _handler )))
281
_error_handler = _older_handler; \
285
#define IF_ERROR else
286
#define FINALLY /* Nothing. */
287
#define RESUME _rethrow = FALSE
289
extern text_t *error_text; /* The text of the last error. */
291
extern jmp_buf *_error_handler; /* The current innermost error handler */
293
extern void _throw( void ) NO_RETURN;
294
/* Call the current error handler.
295
* If there is no current error handler, print error and exit. */
297
extern void complain( string_t message, ... ) NO_RETURN;
298
/* Save the error MESSAGE in ERROR_TEXT.
299
* Additional arguments to "complain" are inserted where
300
* "%s" (string_t ARGUMENT), "%c" (char_t ARGUMENT)
301
* or "%d" (int_t ARGUMENT) is part of MESSAGE. */
303
/* Module initialisation. ===================================================*/
305
extern void init_basic( string_t prog_name );
306
/* Initialise this module. PROG_NAME should be the name of the program. */
308
extern void terminate_basic( void );
309
/* Terminate this module. */
311
/* End of file. =============================================================*/