28 |
#include "m4.h" |
#include "m4.h" |
29 |
#include "m4private.h" |
#include "m4private.h" |
30 |
|
|
31 |
static int decode_char M4_PARAMS((FILE *in)); |
static int decode_char M4_PARAMS((FILE *in)); |
32 |
static void issue_expect_message M4_PARAMS((int expected)); |
static void issue_expect_message M4_PARAMS((int expected)); |
33 |
static int produce_char_dump M4_PARAMS((char *buf, int ch)); |
static int produce_char_dump M4_PARAMS((char *buf, int ch)); |
34 |
static void produce_syntax_dump M4_PARAMS((FILE *file, char ch, int mask)); |
static void produce_syntax_dump M4_PARAMS((FILE *file, char ch, int mask)); |
35 |
|
static void produce_module_dump M4_PARAMS((FILE *file, lt_dlhandle handle)); |
36 |
|
static void produce_symbol_dump M4_PARAMS((FILE *file, |
37 |
|
const m4_symbol *bucke)); |
38 |
|
|
39 |
|
|
40 |
/*------------------------------------------------. |
/*------------------------------------------------. |
41 |
| Produce a frozen state to the given file NAME. | |
| Produce a frozen state to the given file NAME. | |
114 |
fprintf (file, "S%c%d\n%s\n", ch, count, buf); |
fprintf (file, "S%c%d\n%s\n", ch, count, buf); |
115 |
} |
} |
116 |
|
|
117 |
|
/* The modules must be dumped in the order in which they will be |
118 |
|
reloaded from the frozen file. libltdl stores handles in a push |
119 |
|
down stack, so we need to dump them in the reverse order to that. */ |
120 |
|
void |
121 |
|
produce_module_dump (file, handle) |
122 |
|
FILE *file; |
123 |
|
lt_dlhandle handle; |
124 |
|
{ |
125 |
|
lt_dlhandle pending = handle; |
126 |
|
const char *name = m4_module_name (pending); |
127 |
|
|
128 |
|
handle = lt_dlhandle_next (handle); |
129 |
|
if (handle) |
130 |
|
produce_module_dump (file, handle); |
131 |
|
|
132 |
|
fprintf (file, "M%lu\n", (unsigned long) strlen (name)); |
133 |
|
fputs (name, file); |
134 |
|
fputc ('\n', file); |
135 |
|
} |
136 |
|
|
137 |
|
/* Process all entries in one bucket, from the last to the first. |
138 |
|
This order ensures that, at reload time, pushdef's will be |
139 |
|
executed with the oldest definitions first. */ |
140 |
|
void |
141 |
|
produce_symbol_dump (file, bucket) |
142 |
|
FILE *file; |
143 |
|
const m4_symbol *bucket; |
144 |
|
{ |
145 |
|
const m4_symbol *pending = bucket; |
146 |
|
lt_dlhandle handle = SYMBOL_HANDLE (pending); |
147 |
|
const char *symbol_name = SYMBOL_NAME (pending); |
148 |
|
const char *module_name = handle ? m4_module_name (handle) : NULL; |
149 |
|
const m4_builtin *bp; |
150 |
|
|
151 |
|
bucket = SYMBOL_NEXT (bucket); |
152 |
|
if (bucket) |
153 |
|
produce_symbol_dump (file, bucket); |
154 |
|
|
155 |
|
switch (SYMBOL_TYPE (pending)) |
156 |
|
{ |
157 |
|
case M4_TOKEN_TEXT: |
158 |
|
fprintf (file, "T%lu,%lu", |
159 |
|
(unsigned long) strlen (symbol_name), |
160 |
|
(unsigned long) strlen (SYMBOL_TEXT (pending))); |
161 |
|
if (handle) |
162 |
|
fprintf (file, ",%lu", (unsigned long) strlen (module_name)); |
163 |
|
fputc ('\n', file); |
164 |
|
|
165 |
|
fputs (symbol_name, file); |
166 |
|
fputs (SYMBOL_TEXT (pending), file); |
167 |
|
if (handle) |
168 |
|
fputs (module_name, file); |
169 |
|
fputc ('\n', file); |
170 |
|
break; |
171 |
|
|
172 |
|
case M4_TOKEN_FUNC: |
173 |
|
bp = m4_builtin_find_by_func (m4_module_builtins(SYMBOL_HANDLE(pending)), |
174 |
|
SYMBOL_FUNC (pending)); |
175 |
|
if (bp == NULL) |
176 |
|
{ |
177 |
|
M4ERROR ((warning_status, 0, |
178 |
|
_("INTERNAL ERROR: Builtin not found in builtin table!"))); |
179 |
|
abort (); |
180 |
|
} |
181 |
|
|
182 |
|
fprintf (file, "F%lu,%lu", |
183 |
|
(unsigned long) strlen (symbol_name), |
184 |
|
(unsigned long) strlen (bp->name)); |
185 |
|
|
186 |
|
if (handle) |
187 |
|
fprintf (file, ",%lu", |
188 |
|
(unsigned long) strlen (module_name)); |
189 |
|
fputc ('\n', file); |
190 |
|
|
191 |
|
fputs (symbol_name, file); |
192 |
|
fputs (bp->name, file); |
193 |
|
if (handle) |
194 |
|
fputs (module_name, file); |
195 |
|
fputc ('\n', file); |
196 |
|
break; |
197 |
|
|
198 |
|
default: |
199 |
|
M4ERROR ((warning_status, 0, _("\ |
200 |
|
INTERNAL ERROR: Bad token data type in produce_symbol_dump ()"))); |
201 |
|
abort (); |
202 |
|
break; |
203 |
|
} |
204 |
|
} |
205 |
|
|
206 |
void |
void |
207 |
produce_frozen_state (name) |
produce_frozen_state (name) |
208 |
const char *name; |
const char *name; |
209 |
{ |
{ |
210 |
FILE *file; |
FILE *file; |
211 |
int h; |
int h; |
|
m4_symbol *symbol; |
|
|
const m4_builtin *bp; |
|
212 |
|
|
213 |
if (file = fopen (name, "w"), !file) |
if (file = fopen (name, "w"), !file) |
214 |
{ |
{ |
268 |
produce_syntax_dump (file, 'E', 0); |
produce_syntax_dump (file, 'E', 0); |
269 |
|
|
270 |
/* Dump all loaded modules. */ |
/* Dump all loaded modules. */ |
271 |
{ |
produce_module_dump (file, lt_dlhandle_next (0)); |
|
m4_module *module; |
|
|
|
|
|
m4_modules = list_reverse (m4_modules); |
|
|
for (module = (m4_module *) m4_modules; |
|
|
module; module = (m4_module *) LIST_NEXT (module)) |
|
|
{ |
|
|
fprintf (file, "M%lu\n", |
|
|
(unsigned long) strlen (module->modname)); |
|
|
fputs (module->modname, file); |
|
|
fputc ('\n', file); |
|
|
} |
|
|
m4_modules = list_reverse (m4_modules); |
|
|
} |
|
272 |
|
|
273 |
/* Dump all symbols. */ |
/* Dump all symbols. */ |
|
|
|
274 |
for (h = 0; h < hash_table_size; h++) |
for (h = 0; h < hash_table_size; h++) |
275 |
{ |
if (m4_symtab[h]) |
276 |
/* Process all entries in one bucket, from the last to the first. |
produce_symbol_dump (file, m4_symtab[h]); |
|
This order ensures that, at reload time, pushdef's will be |
|
|
executed with the oldest definitions first. */ |
|
|
|
|
|
m4_symtab[h] = (m4_symbol *) list_reverse ((List *) m4_symtab[h]); |
|
|
for (symbol = m4_symtab[h]; symbol; symbol = SYMBOL_NEXT (symbol)) |
|
|
{ |
|
|
const m4_module *module = SYMBOL_MODULE (symbol); |
|
|
const char *symbol_name = SYMBOL_NAME (symbol); |
|
|
const char *modname = module ? module->modname : NULL; |
|
|
|
|
|
switch (SYMBOL_TYPE (symbol)) |
|
|
{ |
|
|
case M4_TOKEN_TEXT: |
|
|
fprintf (file, "T%lu,%lu", |
|
|
(unsigned long) strlen (symbol_name), |
|
|
(unsigned long) strlen (SYMBOL_TEXT (symbol))); |
|
|
if (module) |
|
|
fprintf (file, ",%lu", (unsigned long) strlen (modname)); |
|
|
fputc ('\n', file); |
|
|
|
|
|
fputs (symbol_name, file); |
|
|
fputs (SYMBOL_TEXT (symbol), file); |
|
|
if (module) |
|
|
fputs (modname, file); |
|
|
fputc ('\n', file); |
|
|
break; |
|
|
|
|
|
case M4_TOKEN_FUNC: |
|
|
bp = m4_builtin_find_by_func (NULL, SYMBOL_FUNC (symbol)); |
|
|
if (bp == NULL) |
|
|
{ |
|
|
M4ERROR ((warning_status, 0, _("\ |
|
|
INTERNAL ERROR: Builtin not found in builtin table!"))); |
|
|
abort (); |
|
|
} |
|
|
|
|
|
fprintf (file, "F%lu,%lu", |
|
|
(unsigned long) strlen (symbol_name), |
|
|
(unsigned long) strlen (bp->name)); |
|
|
|
|
|
/* Search for the module that supplied the builtin, if the |
|
|
m4_symbol has no entry. */ |
|
|
if (!module) |
|
|
{ |
|
|
module = (m4_module *) list_find (m4_modules, (VOID *) bp, |
|
|
m4_module_find_by_builtin); |
|
|
modname = module ? module->modname : NULL; |
|
|
} |
|
|
|
|
|
if (module) |
|
|
fprintf (file, ",%lu", |
|
|
(unsigned long) strlen (modname)); |
|
|
fputc ('\n', file); |
|
|
|
|
|
fputs (symbol_name, file); |
|
|
fputs (bp->name, file); |
|
|
if (module) |
|
|
fputs (modname, file); |
|
|
fputc ('\n', file); |
|
|
break; |
|
|
|
|
|
default: |
|
|
M4ERROR ((warning_status, 0, _("\ |
|
|
INTERNAL ERROR: Bad token data type in freeze_one_symbol ()"))); |
|
|
abort (); |
|
|
break; |
|
|
} |
|
|
} |
|
|
|
|
|
/* Reverse the bucket once more, putting it back as it was. */ |
|
|
|
|
|
m4_symtab[h] = (m4_symbol *) list_reverse ((List *) m4_symtab[h]); |
|
|
} |
|
277 |
|
|
278 |
/* Let diversions be issued from output.c module, its cleaner to have this |
/* Let diversions be issued from output.c module, its cleaner to have this |
279 |
piece of code there. */ |
piece of code there. */ |
480 |
VALIDATE ('\n'); |
VALIDATE ('\n'); |
481 |
|
|
482 |
/* Enter a macro having a builtin function as a definition. */ |
/* Enter a macro having a builtin function as a definition. */ |
|
|
|
483 |
{ |
{ |
484 |
const m4_module *module; |
lt_dlhandle handle = 0; |
485 |
m4_builtin *bt = NULL; |
m4_builtin *bt = NULL; |
486 |
|
|
487 |
if (number[2] > 0) |
if (number[2] > 0) |
488 |
{ |
{ |
489 |
module = (m4_module *) list_find (m4_modules, string[2], |
while ((handle = lt_dlhandle_next (handle))) |
490 |
m4_module_find_by_modname); |
if (strcmp (m4_module_name (handle), string[2]) == 0) |
491 |
if (module) |
break; |
492 |
bt = module->bp; |
|
493 |
|
if (handle) |
494 |
|
{ |
495 |
|
bt = m4_module_builtins (handle); |
496 |
|
} |
497 |
} |
} |
498 |
|
|
499 |
bp = m4_builtin_find_by_name (bt, string[1]); |
if (bt) |
500 |
|
bp = m4_builtin_find_by_name (bt, string[1]); |
501 |
|
|
502 |
if (bp) |
if (bp) |
503 |
m4_builtin_define (module, string[0], bp, M4_SYMBOL_PUSHDEF, 0); |
m4_builtin_define (handle, string[0], bp, M4_SYMBOL_PUSHDEF, 0); |
504 |
else |
else |
505 |
M4ERROR ((warning_status, 0, _("\ |
M4ERROR ((warning_status, 0, |
506 |
`%s' from frozen file not found in builtin table!"), |
_("`%s' from frozen file not found in builtin table!"), |
507 |
string[0])); |
string[0])); |
508 |
} |
} |
509 |
break; |
break; |
527 |
GET_STRING (file, string[0], allocated[0], number[0]); |
GET_STRING (file, string[0], allocated[0], number[0]); |
528 |
VALIDATE ('\n'); |
VALIDATE ('\n'); |
529 |
|
|
530 |
m4_module_load (string[0], NULL); |
m4_module_open (string[0], NULL); |
531 |
|
|
532 |
break; |
break; |
533 |
|
|
668 |
|
|
669 |
/* Enter a macro having an expansion text as a definition. */ |
/* Enter a macro having an expansion text as a definition. */ |
670 |
{ |
{ |
671 |
const m4_module *module; |
lt_dlhandle handle = 0; |
672 |
|
|
673 |
if (number[2] > 0) |
if (number[2] > 0) |
674 |
module = (m4_module *) list_find (m4_modules, string[2], |
while ((handle = lt_dlhandle_next (handle))) |
675 |
m4_module_find_by_modname); |
if (strcmp (m4_module_name (handle), string[2]) == 0) |
676 |
|
break; |
677 |
|
|
678 |
m4_macro_define (module, string[0], string[1], M4_SYMBOL_PUSHDEF); |
m4_macro_define (handle, string[0], string[1], M4_SYMBOL_PUSHDEF); |
679 |
} |
} |
680 |
break; |
break; |
681 |
|
|