1
2 /**
3 * @file autogen.h
4 *
5 * Global header file for AutoGen
6 */
7 /**
8 * @mainpage
9 * @section Introduction
10 * Autogen is a multi-component project. There is the basic engine itself
11 * ("autogen"), a library ("libopts") and its support templates (collectively,
12 * "AutoOpts"), several support and utility programs ("columns", "getdefs" and
13 * "xml2ag"), *plus* several handy embedded utility templates. They are all
14 * bundled together because they all require each other.
15 * They each do completely separate things, but they each are not useful
16 * without the other. Thus, they are bundled together.
17 *
18 * @group autogen
19 * @{
20 */
21 /* This file is part of AutoGen.
22 * AutoGen Copyright (C) 1992-2018 by Bruce Korb - all rights reserved
23 *
24 * AutoGen is free software: you can redistribute it and/or modify it
25 * under the terms of the GNU General Public License as published by the
26 * Free Software Foundation, either version 3 of the License, or
27 * (at your option) any later version.
28 *
29 * AutoGen is distributed in the hope that it will be useful, but
30 * WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
32 * See the GNU General Public License for more details.
33 *
34 * You should have received a copy of the GNU General Public License along
35 * with this program. If not, see <http://www.gnu.org/licenses/>.
36 */
37 #ifndef AUTOGEN_BUILD
38 #define AUTOGEN_BUILD 1
39 #include <stdnoreturn.h>
40 #include "compat/unlocked-io.h"
41
42 #include REGEX_HEADER
43 #if !defined(__GNUC__)
44 #define GCC_VERSION 0
45 #elif ! defined(GCC_VERSION)
46 #define GCC_VERSION (__GNUC__ * 10000 \
47 + __GNUC_MINOR__ * 100 \
48 + __GNUC_PATCHLEVEL__)
49 #endif
50
51 #if GCC_VERSION > 40400
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wextra"
54 #pragma GCC diagnostic ignored "-Wconversion"
55 #pragma GCC diagnostic ignored "-Wsign-conversion"
56 #pragma GCC diagnostic ignored "-Wstrict-overflow"
57 #endif
58
59 #include <libguile/scmconfig.h>
60 #include <libguile.h>
61
62 #if GCC_VERSION > 40400
63 #pragma GCC diagnostic pop
64 #endif
65
66 #define DEFINE_FSM
67
68 #include "ag-text.h"
69 #include "opts.h"
70 #include "expr.h"
71 #include "autoopts/autoopts.h"
72 #include "directive.h"
73 #include "snprintfv/printf.h"
74 #include "scribble.h"
75 #include "pseudo-fsm.h"
76
77 #define LOG10_2to32 10 /* rounded up */
78
79 #if defined(SHELL_ENABLED)
80 # ifndef HAVE_WORKING_FORK
81 # error SHELL is enabled and fork() does not work
82 choke me
83 # endif
84 #endif
85
86 #ifndef DIRCH
87 # if defined(_WIN32) && !defined(__CYGWIN__)
88 # define DIRCH '\\'
89 # else
90 # define DIRCH '/'
91 # endif
92 #endif
93
94 #define YYSTYPE t_word
95
96 #define ag_offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
97
98 /*
99 * Dual pipe opening of a child process
100 */
101 typedef struct {
102 int fd_read;
103 int fd_write;
104 } fd_pair_t;
105
106 typedef struct {
107 FILE * fp_read; /* parent read fp */
108 FILE * fp_write; /* parent write fp */
109 } fp_pair_t;
110
111 #define NOPROCESS ((pid_t)-1)
112 #define NULLPROCESS ((pid_t)0)
113 #define NL '\n'
114 #define TAB '\t'
115
116 #include "cgi-fsm.h"
117 #include "defParse-fsm.h"
118
119 typedef union {
120 unsigned char * pzStr;
121 unsigned char ch;
122 } def_token_u_t;
123
124 #define STATE_TABLE /* set up `atexit' and load Guile */ \
125 _State_( INIT ) /* processing command line options */ \
126 _State_( OPTIONS ) /* Loading guile at option time */ \
127 _State_( GUILE_PRELOAD ) /* Loading value definitions */ \
128 _State_( LOAD_DEFS ) /* Loading library template */ \
129 _State_( LIB_LOAD ) /* Loading primary template */ \
130 _State_( LOAD_TPL ) /* processing templates */ \
131 _State_( EMITTING ) /* loading an included template */ \
132 _State_( INCLUDING ) /* end of processing before exit() */ \
133 _State_( CLEANUP ) /* Clean up code in error response */ \
134 _State_( ABORTING ) /* `exit' has been called */ \
135 _State_( DONE )
136
137 #define _State_(n) PROC_STATE_ ## n,
138 typedef enum { STATE_TABLE COUNT_PROC_STATE } proc_state_t;
139 #undef _State_
140
141 #define EXPORT
142
143 typedef struct out_stack out_stack_t;
144 typedef struct out_spec out_spec_t;
145 typedef struct scan_context scan_ctx_t;
146 typedef struct def_entry def_ent_t;
147 typedef struct macro_desc macro_t;
148 typedef struct template_desc templ_t;
149 typedef struct for_state for_state_t;
150 typedef struct tlib_mark tlib_mark_t;
151
152 #define MAX_SUFFIX_LEN 8 /* maximum length of a file name suffix */
153 #define MAX_HEREMARK_LEN 64 /* max length of a here mark */
154 #define SCRIBBLE_SIZE 256 /* much larger than any short name */
155
156 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
157 *
158 * Template Library Layout
159 *
160 * Procedure for loading a template function
161 */
162 typedef macro_t * (load_proc_t)(templ_t *, macro_t *, char const ** ppzScan);
163 typedef load_proc_t * load_proc_p_t;
164
165 typedef void (unload_proc_t)(macro_t *);
166 typedef unload_proc_t * unload_proc_p_t;
167
168 /*
169 * Procedure for handling a template function
170 * during the text emission phase.
171 */
172 typedef macro_t * (hdlr_proc_t)(templ_t *, macro_t *);
173 typedef hdlr_proc_t * hdlr_proc_p_t;
174
175 /*
176 * This must be included after the function prototypes
177 * (the prototypes are used in the generated tables),
178 * but before the macro descriptor structure (the function
179 * enumeration is generated here).
180 */
181 #include "functions.h"
182
183 #define TEMPLATE_REVISION 1
184 #define TEMPLATE_MAGIC_MARKER {{{'A', 'G', 'L', 'B'}}, \
185 TEMPLATE_REVISION, FUNCTION_CKSUM }
186
187 struct tlib_mark {
188 union {
189 unsigned char str[4]; /* {'A', 'G', 'L', 'B'} */
190 unsigned int i[1];
191 } tlm_magic;
192 unsigned short tlm_revision; /* TEMPLATE_REVISION */
193 unsigned short tlm_cksum; /* FUNCTION_CKSUM */
194 };
195
196 /**
197 * Defines for conditional expressions. The first four are an enumeration
198 * that appear in the low four bits and the next-to-lowest four bits.
199 * "PRIMARY_TYPE" and "SECONDARY_TYPE" are masks for extracting this
200 * enumeration. The rest are flags.
201 */
202 #define EMIT_VALUE 0x0000 //!< emit value of variable
203 #define EMIT_EXPRESSION 0x0001 //!< Emit Scheme result
204 #define EMIT_SHELL 0x0002 //!< emit shell output
205 #define EMIT_STRING 0x0003 //!< emit content of expr
206 #define EMIT_PRIMARY_TYPE 0x0007 //!< mask for primary emission type
207 #define EMIT_SECONDARY_TYPE 0x0070 //!< mask for secondary emission type
208 #define EMIT_SECONDARY_SHIFT 4 //!< bit offset for secondary type
209 #define EMIT_IF_ABSENT 0x0100 //!< emit text when value non-existant
210 #define EMIT_ALWAYS 0x0200 //!< emit one of two exprs
211 #define EMIT_FORMATTED 0x0400 //!< format, if val present
212 #define EMIT_NO_DEFINE 0x0800 //!< don't get defined value
213
214 /**
215 * template macro descriptor.
216 */
217 struct macro_desc {
218 mac_func_t md_code; //!< Macro function
219 int md_line; //!< of macro def
220 int md_end_idx; //!< End of block macro
221 int md_sib_idx; //!< Sibling macro (ELIF or SELECT)
222
223 uintptr_t md_name_off; //!< macro name (sometimes)
224 uintptr_t md_txt_off; //!< associated text
225 uintptr_t md_res; //!< some sort of result
226 void * md_pvt; //!< private data for particular macro
227 };
228
229 /**
230 * AutoGen template descriptor.
231 * A full template or a defined macro is managed with this structure.
232 */
233 struct template_desc {
234 tlib_mark_t td_magic; //!< TEMPLATE_MAGIC_MARKER
235 size_t td_size; //!< Structure Size
236 char * td_scan; //!< Next Pointer
237 int td_mac_ct; //!< Count of Macros
238 char const * td_file; //!< Name of template file
239 char * td_name; //!< Defined Macro Name
240 char * td_text; //!< base address of the text
241 char td_start_mac[MAX_SUFFIX_LEN];
242 char td_end_mac[ MAX_SUFFIX_LEN];
243 macro_t td_macros[1]; //!< Array of Macros
244 // char td_text[...]; * strings are at end of macros
245 };
246
247 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
248 *
249 * Name/Value Definitions Layout
250 */
251 typedef enum {
252 VALTYP_UNKNOWN = 0,
253 VALTYP_TEXT,
254 VALTYP_BLOCK
255 } val_typ_t;
256
257
258 #define NO_INDEX ((short)0x80DEAD)
259
260 typedef struct def_ctx def_ctx_t;
261 struct def_ctx {
262 def_ent_t * dcx_defent; //!< ptr to current def set
263 def_ctx_t * dcx_prev; //!< ptr to previous def set
264 };
265
266 typedef union {
267 def_ent_t * dvu_entry;
268 char * dvu_text;
269 } def_val_u;
270
271 struct def_entry {
272 def_ent_t * de_next; //!< next member of same level
273 def_ent_t * de_twin; //!< next member with same name
274 def_ent_t * de_ptwin; //!< previous memb. of level
275 def_ent_t * de_etwin; //!< head of chain to end ptr
276 char * de_name; //!< name of this member
277 long de_index; //!< index among twins
278 def_val_u de_val; //!< string or list of children
279 char * de_file; //!< definition file name
280 int de_line; //!< def file source line
281 val_typ_t de_type; //!< text/block/not defined yet
282 };
283
284 struct scan_context {
285 scan_ctx_t * scx_next;
286 char * scx_scan;
287 char const * scx_fname;
288 char * scx_data;
289 int scx_line;
290 };
291
292 struct out_spec {
293 out_spec_t * os_next;
294 char const * os_file_fmt;
295 bool os_dealloc_fmt;
296 char os_sfx[ 1 ];
297 };
298
299 /**
300 * Output stack handling flags.
301 */
302 #define FPF_FREE 0x0001 /*!< free the fp structure */
303 #define FPF_UNLINK 0x0002 /*!< unlink file (temp file) */
304 #define FPF_NOUNLINK 0x0004 /*!< do not unlink file */
305 #define FPF_STATIC_NM 0x0008 /*!< name statically alloced */
306 #define FPF_NOCHMOD 0x0010 /*!< do not chmod(2) file */
307 #define FPF_TEMPFILE 0x0020 /*!< the file is a temp */
308
309 struct out_stack {
310 int stk_flags;
311 out_stack_t * stk_prev;
312 FILE * stk_fp;
313 char const * stk_fname;
314 };
315
316 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
317 *
318 * FOR loop processing state
319 */
320 /**
321 * The current state of each active FOR loop.
322 */
323 struct for_state {
324 def_ctx_t for_ctx; //!< saved def context for for loop
325 char * for_sep_str; //!< inter-iteration string (allocated)
326 char * for_name; //!< name of iterator (not allocated)
327 int for_from; //!< the first index of loop
328 int for_to; //!< the last index of loop
329 int for_by; //!< the loop increment (usually 1)
330 int for_index; //!< the current index
331 bool for_loading; //!< the FOR macro is getting ready
332 bool for_islast; //!< true for last iteration
333 bool for_isfirst; //!< true for first iteration
334 bool for_not_found;//!< usually false, true with sparse arrays
335 jmp_buf for_env; //!< long jump buffer (BREAK, CONTINUE)
336 };
337
338 typedef enum {
339 LOOP_JMP_OKAY = 0,
340 LOOP_JMP_NEXT = 1,
341 LOOP_JMP_BREAK = 2
342 } loop_jmp_type_t;
343
344 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
345 /**
346 * Invocation of a defined macro processing state
347 */
348 typedef struct ivk_info ivk_info_t;
349 struct ivk_info {
350 ivk_info_t * ii_prev; //!< previous layer
351 int ii_depth; //!< Invocation nesting depth
352 jmp_buf ii_env; //!< long jump buffer (RETURN)
353 int ii_for_depth; //!< for depth for this invocation
354 int ii_for_alloc; //!< for state buffer allocation count
355 for_state_t * ii_for_data; //!< array of "for" macro states
356 };
357 #define IVK_INFO_INITIALIZER(_p) { \
358 .ii_prev = (_p), \
359 .ii_depth = curr_ivk_info->ii_depth + 1, \
360 .ii_for_depth = 0, \
361 .ii_for_alloc = 0, \
362 .ii_for_data = NULL \
363 }
364
365 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
366 *
367 * Parsing stuff
368 */
369 #define _MkStr(_s) #_s
370 #define MK_STR(_s) _MkStr(_s)
371
372 #define SCM_EVAL_CONST(_s) \
373 do { static int const line = __LINE__ - 1; \
374 static char const file[] = __FILE__; \
375 static char const * text = _s; \
376 last_scm_cmd = text; \
377 ag_scm_c_eval_string_from_file_line(text, file, line); \
378 } while (false)
379
380 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
381 *
382 * GLOBAL VARIABLES
383 *
384 * General Processing Globals
385 */
386 #define ag_pname autogenOptions.pzProgName
387 MODE proc_state_t processing_state VALUE( PROC_STATE_INIT );
388 MODE unsigned int include_depth VALUE( 0 );
389 MODE bool defining_macro VALUE( false );
390 MODE templ_t * named_tpls VALUE( NULL );
391 MODE char const * oops_pfx VALUE( "" );
392 /*
393 * "eval_mac_expr" must be able to return a distinct empty string so that
394 * the "CASE" function can distinguish an empty string due to it being a
395 * value from an empty string due to an absent definition.
396 */
397 MODE char const no_def_str[1] VALUE( "" );
398
399 /*
400 * Template Processing Globals
401 */
402 MODE char const * curr_sfx VALUE( NULL );
403 /**
404 * The time to set for the modification times of the output files.
405 */
406 #ifndef HAVE_CLOCK_GETTIME
407 #undef HAVE_UTIMENSAT
408 #endif
409
410 #ifndef HAVE_UTIMENSAT
411 MODE time_t outfile_time VALUE( 0 );
412 MODE time_t maxfile_time VALUE( 0 );
413 #define time_is_before(_f, _s) ((_f) < (_s))
414
415 #else // HAVE_UTIMENSAT
416 #ifdef DEFINING
417 MODE struct timespec outfile_time = {0, UTIME_OMIT};
418 MODE struct timespec maxfile_time = {0, UTIME_OMIT};
419 #else
420 MODE struct timespec outfile_time, maxfile_time;
421 #endif
422
423 #define time_is_before(_f, _s) ( \
424 ((_f).tv_sec < (_s).tv_sec) \
425 || ( (((_f).tv_sec == (_s).tv_sec)) \
426 && (((_f).tv_nsec < (_s).tv_nsec)) ) \
427 )
428 #undef st_atime
429 #define st_atime st_atim
430 #undef st_mtime
431 #define st_mtime st_mtim
432 #undef st_ctime
433 #define st_ctime st_ctim
434 #endif // HAVE_UTIMENSAT
435
436 /**
437 * The original time autogen started
438 */
439 MODE time_t start_time VALUE( 0 );
440 MODE out_stack_t * cur_fpstack VALUE( NULL );
441 MODE out_spec_t * output_specs VALUE( NULL );
442 MODE jmp_buf abort_jmp_buf;
443 MODE ivk_info_t root_ivk_info VALUE( { 0 } );
444 MODE ivk_info_t * curr_ivk_info VALUE( &root_ivk_info );
445 MODE for_state_t * for_state VALUE( NULL );
446 MODE FILE * trace_fp VALUE( NULL );
447 /**
448 * temporary file name template
449 */
450 MODE char const * pz_temp_tpl VALUE( NULL );
451 /**
452 * Length of the template that is the temp directory
453 */
454 MODE size_t temp_tpl_dir_len VALUE( 0 );
455 /**
456 * dependency file file pointer.
457 */
458 MODE FILE * dep_fp VALUE( NULL );
459 /**
460 * name of target of rule
461 */
462 MODE char const * dep_target VALUE( NULL );
463 /**
464 * name of dependency file
465 */
466 MODE char const * dep_file VALUE( NULL );
467 /**
468 * base name of both source and derived files.
469 * Either "_TList" or "_SList" gets put on the end.
470 */
471 MODE char const * pz_targ_base VALUE( NULL );
472 /**
473 * The actual list of input (source) files.
474 */
475 MODE char const * source_list VALUE( NULL );
476 MODE size_t source_size VALUE( 0 );
477 MODE size_t source_used VALUE( 0 );
478 MODE bool dep_phonies VALUE( false );
479 MODE char * cgi_stderr VALUE( NULL );
480
481 MODE char const * server_args[2] VALUE( { NULL } );
482 MODE char const * shell_program VALUE( MK_STR(CONFIG_SHELL) );
483 MODE char const * libguile_ver VALUE( NULL );
484
485 /*
486 * AutoGen definiton and template context
487 *
488 * curr_def_ctx is the current, active list of name/value pairs.
489 * Points to its parent list for full search resolution.
490 *
491 * current_tpl the template (and DEFINE macro) from which
492 * the current set of macros is being extracted.
493 *
494 * These are set in exactly ONE place:
495 * On entry to the dispatch routine (gen_block). Two routines, however,
496 * must restore the values: mFunc_Define and mFunc_For. They are the only
497 * routines that dynamically push name/value pairs on the definition stack.
498 */
499 MODE def_ctx_t curr_def_ctx VALUE( { NULL } );
500 MODE def_ctx_t root_def_ctx VALUE( { NULL } );
501 MODE templ_t * current_tpl VALUE( NULL );
502 MODE char const * last_scm_cmd VALUE( NULL );
503
504 /*
505 * Current Macro
506 *
507 * This may be set in exactly three places:
508 * 1. The dispatch routine (gen_block) that steps through
509 * a list of macros
510 * 2. mFunc_If may transfer to one of its 'ELIF' or 'ELSE'
511 * alternation macros
512 * 3. mFunc_Case may transfer to one of its selection clauses.
513 */
514 MODE macro_t * cur_macro VALUE( NULL );
515 MODE tlib_mark_t const magic_marker VALUE( TEMPLATE_MAGIC_MARKER );
516
517 /*
518 * Template Parsing Globals
519 */
520 MODE int tpl_line VALUE( 1 );
521 MODE scan_ctx_t * base_ctx VALUE( NULL );
522 MODE scan_ctx_t * cctx VALUE( NULL );
523 MODE scan_ctx_t * end_ctx VALUE( NULL );
524 MODE size_t end_mac_len VALUE( 0 );
525 MODE char end_mac_mark[8] VALUE( "" );
526 MODE size_t st_mac_len VALUE( 0 );
527 MODE char st_mac_mark[8] VALUE( "" );
528 MODE out_stack_t out_root VALUE({ 0 });
529
530 #define name_sep_ch '.'
531
532 /*
533 * Definition Parsing Globals
534 */
535 MODE char * token_str VALUE( NULL );
536 MODE te_dp_event token_code VALUE( DP_EV_INVALID );
537
538 MODE int ent_stack_depth VALUE( 0 );
539 MODE int ent_stack_sz VALUE( 16 );
540 MODE def_ent_t * dft_ent_stack[16] VALUE( { 0 } );
541 MODE def_ent_t ** ent_stack VALUE( dft_ent_stack );
542 MODE def_ent_t * curr_ent VALUE( NULL );
543
544 MODE autogen_exit_code_t ag_exit_code VALUE( AUTOGEN_EXIT_OPTION_ERROR );
545
546 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
547 *
548 * IF we have fopencookie or funopen, then we also have our own fmemopen
549 */
550 #ifdef ENABLE_FMEMOPEN
551 extern FILE * ag_fmemopen(void *buf, ssize_t len, char const *mode);
552 extern int ag_fmemioctl(FILE * fp, int req, ...);
553 #endif
554
555 typedef union {
556 const void * cp;
557 void * p;
558 } v2c_t;
559 MODE v2c_t p2p VALUE( { NULL } );
560
561 #ifdef DEBUG_ENABLED
562 # define AG_ABEND(s) ag_abend_at(s,__FILE__,__LINE__)
563 #else
564 # define AG_ABEND(s) ag_abend_at(s)
565 #endif
566 #define AG_CANT(_op, _wh) \
567 AG_ABEND(aprf(CANNOT_FMT, errno, _op, _wh, strerror(errno)))
568
569 #ifdef DEBUG_FSM
570 # define DEBUG
571 #else
572 # undef DEBUG
573 #endif
574
575 #define AG_ABEND_IN(t,m,s) \
576 STMTS( current_tpl=(t); cur_macro=(m); AG_ABEND(s);)
577
578 #if __STDC_VERSION__ < 199901L
579 # if __GNUC__ >= 2
580 # define __func__ __FUNCTION__
581 # else
582 # define __func__ "<unknown>"
583 # endif
584 #endif
585
586 /*
587 * Code variations based on the version of Guile:
588 */
589 #include "guile-iface.h"
590 #include "proto.h"
591
592 /**
593 * Evaluate a scheme expression, setting the file and line number from
594 * the file and line of the currently active macro.
595 *
596 * @param[in] str the scheme expression
597 * @returns the SCM result. That may be SCM_UNDEFINED.
598 */
ag_eval(char const * str)599 static inline SCM ag_eval(char const * str)
600 {
601 SCM res;
602 char const * sv = last_scm_cmd; /* Watch for nested calls */
603 last_scm_cmd = str;
604
605 res = ag_scm_c_eval_string_from_file_line(
606 str, current_tpl->td_file, cur_macro->md_line);
607
608 last_scm_cmd = sv;
609 return res;
610 }
611
612 /**
613 * Extracted from guile-iface stuff. Seems to be stable since for at least
614 * 1.6.0 through 2.0.0. 1.4.x is thoroughly dead now (May, 2011).
615 */
616 #define AG_SCM_DISPLAY(_s) \
617 scm_display(_s, scm_current_output_port())
618
619 #define AG_SCM_BOOT_GUILE(_ac, _av, _im) \
620 scm_boot_guile((_ac), (_av), (_im), NULL)
621
622 #define AG_SCM_APPLY2(_op, _f, _tst) \
623 scm_apply(_op, _f, scm_cons(_tst, scm_list_1(SCM_EOL)))
624
625 #define AG_SCM_CHAR_P(_c) SCM_CHARP(_c)
626
627 /**
628 * Hide dummy functions from complexity measurement tools
629 */
630 #define HIDE_FN(_t) _t
631
632 #endif /* AUTOGEN_BUILD */
633 /** @}
634 *
635 * Local Variables:
636 * mode: C
637 * c-file-style: "stroustrup"
638 * indent-tabs-mode: nil
639 * End:
640 * end of agen5/autogen.h */
641