1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620 |
- /* Gengtype persistent state serialization & de-serialization.
- Useful for gengtype in plugin mode.
- Copyright (C) 2010-2015 Free Software Foundation, Inc.
- This file is part of GCC.
- GCC 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 3, or (at your option) any later
- version.
- GCC 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 GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>.
- Contributed by Jeremie Salvucci <jeremie.salvucci@free.fr>
- and Basile Starynkevitch <basile@starynkevitch.net>
- */
- #ifdef HOST_GENERATOR_FILE
- #include "config.h"
- #define GENERATOR_FILE 1
- #else
- #include "bconfig.h"
- #endif
- #include "system.h"
- #include "errors.h" /* For fatal. */
- #include "hashtab.h"
- #include "version.h" /* For version_string & pkgversion_string. */
- #include "obstack.h"
- #include "gengtype.h"
- /* Gives the file location of a type, if any. */
- static inline struct fileloc*
- type_lineloc (const_type_p ty)
- {
- if (!ty)
- return NULL;
- switch (ty->kind)
- {
- case TYPE_NONE:
- gcc_unreachable ();
- case TYPE_STRUCT:
- case TYPE_UNION:
- case TYPE_LANG_STRUCT:
- case TYPE_USER_STRUCT:
- case TYPE_UNDEFINED:
- return CONST_CAST (struct fileloc*, &ty->u.s.line);
- case TYPE_SCALAR:
- case TYPE_STRING:
- case TYPE_POINTER:
- case TYPE_ARRAY:
- return NULL;
- default:
- gcc_unreachable ();
- }
- }
- /* The state file has simplistic lispy lexical tokens. Its lexer gives
- a linked list of struct state_token_st, through the peek_state_token
- function. Lexical tokens are consumed with next_state_tokens. */
- /* The lexical kind of each lispy token. */
- enum state_token_en
- {
- STOK_NONE, /* Never used. */
- STOK_INTEGER, /* Integer token. */
- STOK_STRING, /* String token. */
- STOK_LEFTPAR, /* Left opening parenthesis. */
- STOK_RIGHTPAR, /* Right closing parenthesis. */
- STOK_NAME /* hash-consed name or identifier. */
- };
- /* Structure and hash-table used to share identifiers or names. */
- struct state_ident_st
- {
- /* TODO: We could improve the parser by reserving identifiers for
- state keywords and adding a keyword number for them. That would
- mean adding another field in this state_ident_st struct. */
- char stid_name[1]; /* actually bigger & null terminated */
- };
- static htab_t state_ident_tab;
- /* The state_token_st structure is for lexical tokens in the read
- state file. The stok_kind field discriminates the union. Tokens
- are allocated by peek_state_token which calls read_a_state_token
- which allocate them. Tokens are freed by calls to
- next_state_tokens. Token are organized in a FIFO look-ahead queue
- filled by peek_state_token. */
- struct state_token_st
- {
- enum state_token_en stok_kind; /* the lexical kind
- discriminates the stok_un
- union */
- int stok_line; /* the line number */
- int stok_col; /* the column number */
- const char *stok_file; /* the file path */
- struct state_token_st *stok_next; /* the next token in the
- queue, when peeked */
- union /* discriminated by stok_kind! */
- {
- int stok_num; /* when STOK_INTEGER */
- char stok_string[1]; /* when STOK_STRING, actual size is
- bigger and null terminated */
- struct state_ident_st *stok_ident; /* when STOK_IDENT */
- void *stok_ptr; /* null otherwise */
- }
- stok_un;
- };
- #define NULL_STATE_TOKEN (struct state_token_st*)0
- /* the state_token pointer contains the leftmost current token. The
- tokens are organized in a linked queue, using stok_next, for token
- look-ahead. */
- struct state_token_st *state_token = NULL_STATE_TOKEN;
- /* Used by the reading lexer. */
- static FILE *state_file;
- static const char *state_path = NULL;
- static int state_line = 0;
- static long state_bol = 0; /* offset of beginning of line */
- /* A class for writing out s-expressions, keeping track of newlines and
- nested indentation. */
- class s_expr_writer
- {
- public:
- s_expr_writer ();
- void write_new_line ();
- void write_any_indent (int leading_spaces);
- void begin_s_expr (const char *tag);
- void end_s_expr ();
- private:
- int m_indent_amount;
- int m_had_recent_newline;
- }; // class s_expr_writer
- /* A class for writing out "gtype.state". */
- class state_writer : public s_expr_writer
- {
- public:
- state_writer ();
- private:
- void write_state_fileloc (struct fileloc *floc);
- void write_state_fields (pair_p fields);
- void write_state_a_string (const char *s);
- void write_state_string_option (options_p current);
- void write_state_type_option (options_p current);
- void write_state_nested_option (options_p current);
- void write_state_option (options_p current);
- void write_state_options (options_p opt);
- void write_state_lang_bitmap (lang_bitmap bitmap);
- void write_state_version (const char *version);
- void write_state_scalar_type (type_p current);
- void write_state_string_type (type_p current);
- void write_state_undefined_type (type_p current);
- void write_state_struct_union_type (type_p current, const char *kindstr);
- void write_state_struct_type (type_p current);
- void write_state_user_struct_type (type_p current);
- void write_state_union_type (type_p current);
- void write_state_lang_struct_type (type_p current);
- void write_state_pointer_type (type_p current);
- void write_state_array_type (type_p current);
- void write_state_gc_used (enum gc_used_enum gus);
- void write_state_common_type_content (type_p current);
- void write_state_type (type_p current);
- void write_state_pair (pair_p current);
- int write_state_pair_list (pair_p list);
- void write_state_typedefs (void);
- void write_state_structures (void);
- void write_state_variables (void);
- void write_state_srcdir (void);
- void write_state_files_list (void);
- void write_state_languages (void);
- friend void write_state (const char *state_path);
- private:
- /* Counter of written types. */
- int m_state_written_type_count;
- }; // class state_writer
- /* class s_expr_writer's trivial constructor. */
- s_expr_writer::s_expr_writer ()
- : m_indent_amount (0),
- m_had_recent_newline (0)
- {
- }
- /* Write a newline to the output file, merging adjacent newlines. */
- void
- s_expr_writer::write_new_line (void)
- {
- /* Don't add a newline if we've just had one. */
- if (!m_had_recent_newline)
- {
- fprintf (state_file, "\n");
- m_had_recent_newline = 1;
- }
- }
- /* If we've just had a newline, write the indentation amount, potentially
- omitting some spaces.
- LEADING_SPACES exists to support code that writes strings with leading
- spaces (e.g " foo") which might occur within a line, or could be the first
- thing on a line. By passing leading_spaces == 1, when such a string is the
- first thing on a line, write_any_indent () swallows the successive
- leading spaces into the indentation so that the "foo" begins at the expected
- column. */
- void
- s_expr_writer::write_any_indent (int leading_spaces)
- {
- int i;
- int amount = m_indent_amount - leading_spaces;
- if (m_had_recent_newline)
- for (i = 0; i < amount; i++)
- fprintf (state_file, " ");
- m_had_recent_newline = 0;
- }
- /* Write the beginning of a new s-expresion e.g. "(!foo "
- The writer automatically adds whitespace to show the hierarchical
- structure of the expressions, so each one starts on a new line,
- and any within it will be at an increased indentation level. */
- void
- s_expr_writer::begin_s_expr (const char *tag)
- {
- write_new_line ();
- write_any_indent (0);
- fprintf (state_file, "(!%s ", tag);
- m_indent_amount++;
- }
- /* Write out the end of an s-expression: any necssessary indentation,
- a closing parenthesis, and a new line. */
- void
- s_expr_writer::end_s_expr (void)
- {
- m_indent_amount--;
- write_any_indent (0);
- fprintf (state_file, ")");
- write_new_line ();
- }
- /* class state_writer's trivial constructor. */
- state_writer::state_writer ()
- : s_expr_writer (),
- m_state_written_type_count (0)
- {
- }
- /* Fatal error messages when reading the state. They are extremely
- unlikely, and only appear when this gengtype-state.c file is buggy,
- or when reading a gengtype state which was not generated by the
- same version of gengtype or GCC. */
- /* Fatal message while reading state. */
- static void
- fatal_reading_state (struct state_token_st* tok, const char*msg)
- {
- if (tok)
- fatal ("%s:%d:%d: Invalid state file; %s",
- tok->stok_file, tok->stok_line, tok->stok_col,
- msg);
- else
- fatal ("%s:%d: Invalid state file; %s",
- state_path, state_line, msg);
- }
- /* Fatal printf-like message while reading state. This can't be a
- function, because there is no way to pass a va_arg to a variant of
- fatal. */
- #define fatal_reading_state_printf(Tok,Fmt,...) do { \
- struct state_token_st* badtok = Tok; \
- if (badtok) \
- fatal ("%s:%d:%d: Invalid state file; " Fmt, \
- badtok->stok_file, \
- badtok->stok_line, \
- badtok->stok_col, __VA_ARGS__); \
- else \
- fatal ("%s:%d: Invalid state file; " Fmt, \
- state_path, state_line, __VA_ARGS__); \
- } while (0)
- /* Find or allocate an identifier in our name hash table. */
- static struct state_ident_st *
- state_ident_by_name (const char *name, enum insert_option optins)
- {
- PTR *slot = NULL;
- int namlen = 0;
- struct state_ident_st *stid = NULL;
- if (!name || !name[0])
- return NULL;
- slot = htab_find_slot (state_ident_tab, name, optins);
- if (!slot)
- return NULL;
- namlen = strlen (name);
- stid =
- (struct state_ident_st *) xmalloc (sizeof (struct state_ident_st) +
- namlen);
- memset (stid, 0, sizeof (struct state_ident_st) + namlen);
- strcpy (stid->stid_name, name);
- *slot = stid;
- return stid;
- }
- /* Our token lexer is heavily inspired by MELT's lexer, and share some
- code with the file gcc/melt-runtime.c of the GCC MELT branch! We
- really want the gengtype state to be easily parsable by MELT. This
- is a usual lispy lexing routine, dealing with spaces and comments,
- numbers, parenthesis, names, strings. */
- static struct state_token_st *
- read_a_state_token (void)
- {
- int c = 0;
- long curoff = 0;
- struct state_token_st *tk = NULL;
- again: /* Read again, e.g. after a comment or spaces. */
- c = getc (state_file);
- if (c == EOF)
- return NULL;
- /* Handle spaces, count lines. */
- if (c == '\n')
- {
- state_line++;
- state_bol = curoff = ftell (state_file);
- goto again;
- };
- if (ISSPACE (c))
- goto again;
- /* Skip comments starting with semi-colon. */
- if (c == ';')
- {
- do
- {
- c = getc (state_file);
- }
- while (c > 0 && c != '\n');
- if (c == '\n')
- {
- state_line++;
- state_bol = curoff = ftell (state_file);
- }
- goto again;
- };
- /* Read signed numbers. */
- if (ISDIGIT (c) || c == '-' || c == '+')
- { /* number */
- int n = 0;
- ungetc (c, state_file);
- curoff = ftell (state_file);
- if (fscanf (state_file, "%d", &n) <= 0)
- fatal_reading_state (NULL_STATE_TOKEN, "Lexical error in number");
- tk = XCNEW (struct state_token_st);
- tk->stok_kind = STOK_INTEGER;
- tk->stok_line = state_line;
- tk->stok_col = curoff - state_bol;
- tk->stok_file = state_path;
- tk->stok_next = NULL;
- tk->stok_un.stok_num = n;
- return tk;
- }
- /* Read an opening left parenthesis. */
- else if (c == '(')
- {
- curoff = ftell (state_file);
- tk = XCNEW (struct state_token_st);
- tk->stok_kind = STOK_LEFTPAR;
- tk->stok_line = state_line;
- tk->stok_col = curoff - state_bol;
- tk->stok_file = state_path;
- tk->stok_next = NULL;
- return tk;
- }
- /* Read an closing right parenthesis. */
- else if (c == ')')
- {
- curoff = ftell (state_file);
- tk = XCNEW (struct state_token_st);
- tk->stok_kind = STOK_RIGHTPAR;
- tk->stok_line = state_line;
- tk->stok_col = curoff - state_bol;
- tk->stok_file = state_path;
- tk->stok_next = NULL;
- return tk;
- }
- /* Read identifiers, using an obstack. */
- else if (ISALPHA (c) || c == '_' || c == '$' || c == '!' || c == '#')
- {
- struct obstack id_obstack;
- struct state_ident_st *sid = NULL;
- char *ids = NULL;
- obstack_init (&id_obstack);
- curoff = ftell (state_file);
- while (ISALNUM (c) || c == '_' || c == '$' || c == '!' || c == '#')
- {
- obstack_1grow (&id_obstack, c);
- c = getc (state_file);
- if (c < 0)
- break;
- };
- if (c >= 0)
- ungetc (c, state_file);
- obstack_1grow (&id_obstack, (char) 0);
- ids = XOBFINISH (&id_obstack, char *);
- sid = state_ident_by_name (ids, INSERT);
- obstack_free (&id_obstack, NULL);
- ids = NULL;
- tk = XCNEW (struct state_token_st);
- tk->stok_kind = STOK_NAME;
- tk->stok_line = state_line;
- tk->stok_col = curoff - state_bol;
- tk->stok_file = state_path;
- tk->stok_next = NULL;
- tk->stok_un.stok_ident = sid;
- return tk;
- }
- /* Read a string, dealing with escape sequences a la C! */
- else if (c == '"')
- {
- char *cstr = NULL;
- int cslen = 0;
- struct obstack bstring_obstack;
- obstack_init (&bstring_obstack);
- curoff = ftell (state_file);
- while ((c = getc (state_file)) != '"' && c >= 0)
- {
- if (ISPRINT (c) && c != '\\')
- obstack_1grow (&bstring_obstack, (char) c);
- else if (ISSPACE (c) && c != '\n')
- obstack_1grow (&bstring_obstack, (char) c);
- else if (c == '\\')
- {
- c = getc (state_file);
- switch (c)
- {
- case 'a':
- obstack_1grow (&bstring_obstack, '\a');
- c = getc (state_file);
- break;
- case 'b':
- obstack_1grow (&bstring_obstack, '\b');
- c = getc (state_file);
- break;
- case 't':
- obstack_1grow (&bstring_obstack, '\t');
- c = getc (state_file);
- break;
- case 'n':
- obstack_1grow (&bstring_obstack, '\n');
- c = getc (state_file);
- break;
- case 'v':
- obstack_1grow (&bstring_obstack, '\v');
- c = getc (state_file);
- break;
- case 'f':
- obstack_1grow (&bstring_obstack, '\f');
- c = getc (state_file);
- break;
- case 'r':
- obstack_1grow (&bstring_obstack, '\r');
- c = getc (state_file);
- break;
- case '"':
- obstack_1grow (&bstring_obstack, '\"');
- c = getc (state_file);
- break;
- case '\\':
- obstack_1grow (&bstring_obstack, '\\');
- c = getc (state_file);
- break;
- case ' ':
- obstack_1grow (&bstring_obstack, ' ');
- c = getc (state_file);
- break;
- case 'x':
- {
- unsigned int cx = 0;
- if (fscanf (state_file, "%02x", &cx) > 0 && cx > 0)
- obstack_1grow (&bstring_obstack, cx);
- else
- fatal_reading_state
- (NULL_STATE_TOKEN,
- "Lexical error in string hex escape");
- c = getc (state_file);
- break;
- }
- default:
- fatal_reading_state
- (NULL_STATE_TOKEN,
- "Lexical error - unknown string escape");
- }
- }
- else
- fatal_reading_state (NULL_STATE_TOKEN, "Lexical error...");
- };
- if (c != '"')
- fatal_reading_state (NULL_STATE_TOKEN, "Unterminated string");
- obstack_1grow (&bstring_obstack, '\0');
- cstr = XOBFINISH (&bstring_obstack, char *);
- cslen = strlen (cstr);
- tk = (struct state_token_st *)
- xcalloc (sizeof (struct state_token_st) + cslen, 1);
- tk->stok_kind = STOK_STRING;
- tk->stok_line = state_line;
- tk->stok_col = curoff - state_bol;
- tk->stok_file = state_path;
- tk->stok_next = NULL;
- strcpy (tk->stok_un.stok_string, cstr);
- obstack_free (&bstring_obstack, NULL);
- return tk;
- }
- /* Got an unexpected character. */
- fatal_reading_state_printf
- (NULL_STATE_TOKEN,
- "Lexical error at offset %ld - bad character \\%03o = '%c'",
- ftell (state_file), c, c);
- }
- /* Used for lexical look-ahead. Retrieves the lexical token of rank
- DEPTH, starting with 0 when reading the state file. Gives null on
- end of file. */
- static struct state_token_st *
- peek_state_token (int depth)
- {
- int remdepth = depth;
- struct state_token_st **ptoken = &state_token;
- struct state_token_st *tok = NULL;
- while (remdepth >= 0)
- {
- if (*ptoken == NULL)
- {
- *ptoken = tok = read_a_state_token ();
- if (tok == NULL)
- return NULL;
- }
- tok = *ptoken;
- ptoken = &((*ptoken)->stok_next);
- remdepth--;
- }
- return tok;
- }
- /* Consume the next DEPTH tokens and free them. */
- static void
- next_state_tokens (int depth)
- {
- struct state_token_st *n;
- while (depth > 0)
- {
- if (state_token != NULL)
- {
- n = state_token->stok_next;
- free (state_token);
- state_token = n;
- }
- else
- fatal_reading_state (NULL_STATE_TOKEN, "Tokens stack empty");
- depth--;
- }
- }
- /* Safely retrieve the lexical kind of a token. */
- static inline enum state_token_en
- state_token_kind (struct state_token_st *p)
- {
- if (p == NULL)
- return STOK_NONE;
- else
- return p->stok_kind;
- }
- /* Test if a token is a given name i.e. an identifier. */
- static inline bool
- state_token_is_name (struct state_token_st *p, const char *name)
- {
- if (p == NULL)
- return false;
- if (p->stok_kind != STOK_NAME)
- return false;
- return !strcmp (p->stok_un.stok_ident->stid_name, name);
- }
- /* Following routines are useful for serializing datas.
- *
- * We want to serialize :
- * - typedefs list
- * - structures list
- * - variables list
- *
- * So, we have one routine for each kind of data. The main writing
- * routine is write_state. The main reading routine is
- * read_state. Most writing routines write_state_FOO have a
- * corresponding reading routine read_state_FOO. Reading is done in a
- * recursive descending way, and any read error is fatal.
- */
- /* When reading the state, we need to remember the previously seen
- types by their state_number, since GTY-ed types are usually
- shared. */
- static htab_t state_seen_types;
- /* Return the length of a linked list made of pairs. */
- static int pair_list_length (pair_p list);
- /* Compute the length of a list of pairs, starting from the first
- one. */
- static int
- pair_list_length (pair_p list)
- {
- int nbpair = 0;
- pair_p l = NULL;
- for (l = list; l; l = l->next)
- nbpair++;
- return nbpair;
- }
- /* Write a file location. Files relative to $(srcdir) are quite
- frequent and are handled specially. This ensures that two gengtype
- state file-s produced by gengtype on the same GCC source tree are
- very similar and can be reasonably compared with diff, even if the
- two GCC source trees have different absolute paths. */
- void
- state_writer::write_state_fileloc (struct fileloc *floc)
- {
- if (floc != NULL && floc->line > 0)
- {
- const char *srcrelpath = NULL;
- gcc_assert (floc->file != NULL);
- /* Most of the files are inside $(srcdir) so it is worth to
- handle them specially. */
- srcrelpath = get_file_srcdir_relative_path (floc->file);
- if (srcrelpath != NULL)
- {
- begin_s_expr ("srcfileloc");
- write_state_a_string (srcrelpath);
- }
- else
- {
- begin_s_expr ("fileloc");
- write_state_a_string (get_input_file_name (floc->file));
- }
- fprintf (state_file, " %d", floc->line);
- end_s_expr ();
- }
- else
- fprintf (state_file, "nil ");
- }
- /* Write a list of fields. */
- void
- state_writer::write_state_fields (pair_p fields)
- {
- int nbfields = pair_list_length (fields);
- int nbpairs = 0;
- begin_s_expr ("fields");
- fprintf (state_file, "%d ", nbfields);
- nbpairs = write_state_pair_list (fields);
- gcc_assert (nbpairs == nbfields);
- end_s_expr ();
- }
- /* Write a null-terminated string in our lexical convention, very
- similar to the convention of C. */
- void
- state_writer::write_state_a_string (const char *s)
- {
- char c;
- write_any_indent (1);
- fputs (" \"", state_file);
- for (; *s != 0; s++)
- {
- c = *s;
- switch (c)
- {
- case '\a':
- fputs ("\\a", state_file);
- break;
- case '\b':
- fputs ("\\b", state_file);
- break;
- case '\t':
- fputs ("\\t", state_file);
- break;
- case '\n':
- fputs ("\\n", state_file);
- break;
- case '\v':
- fputs ("\\v", state_file);
- break;
- case '\f':
- fputs ("\\f", state_file);
- break;
- case '\r':
- fputs ("\\r", state_file);
- break;
- case '\"':
- fputs ("\\\"", state_file);
- break;
- case '\\':
- fputs ("\\\\", state_file);
- break;
- default:
- if (ISPRINT (c))
- putc (c, state_file);
- else
- fprintf (state_file, "\\x%02x", (unsigned) c);
- }
- }
- fputs ("\"", state_file);
- }
- /* Our option-s have three kinds, each with its writer. */
- void
- state_writer::write_state_string_option (options_p current)
- {
- write_any_indent (0);
- fprintf (state_file, "string ");
- if (current->info.string != NULL)
- write_state_a_string (current->info.string);
- else
- fprintf (state_file, " nil ");
- }
- void
- state_writer::write_state_type_option (options_p current)
- {
- write_any_indent (0);
- fprintf (state_file, "type ");
- write_state_type (current->info.type);
- }
- void
- state_writer::write_state_nested_option (options_p current)
- {
- write_any_indent (0);
- fprintf (state_file, "nested ");
- write_state_type (current->info.nested->type);
- if (current->info.nested->convert_from != NULL)
- write_state_a_string (current->info.nested->convert_from);
- else
- {
- write_any_indent (1);
- fprintf (state_file, " nil ");
- }
- if (current->info.nested->convert_to != NULL)
- write_state_a_string (current->info.nested->convert_to);
- else
- {
- write_any_indent (1);
- fprintf (state_file, " nil ");
- }
- }
- void
- state_writer::write_state_option (options_p current)
- {
- begin_s_expr ("option");
- write_any_indent (0);
- if (current->name != NULL)
- fprintf (state_file, "%s ", current->name);
- else
- fprintf (state_file, "nil ");
- switch (current->kind)
- {
- case OPTION_STRING:
- write_state_string_option (current);
- break;
- case OPTION_TYPE:
- write_state_type_option (current);
- break;
- case OPTION_NESTED:
- write_state_nested_option (current);
- break;
- default:
- fatal ("Option tag unknown");
- }
- /* Terminate the "option" s-expression. */
- end_s_expr ();
- }
- /* Write a list of GTY options. */
- void
- state_writer::write_state_options (options_p opt)
- {
- options_p current;
- if (opt == NULL)
- {
- write_any_indent (0);
- fprintf (state_file, "nil ");
- return;
- }
- begin_s_expr ("options");
- for (current = opt; current != NULL; current = current->next)
- write_state_option (current);
- end_s_expr ();
- }
- /* Write a bitmap representing a set of GCC front-end languages. */
- void
- state_writer::write_state_lang_bitmap (lang_bitmap bitmap)
- {
- write_any_indent (0);
- fprintf (state_file, "%d ", (int) bitmap);
- }
- /* Write version information. */
- void
- state_writer::write_state_version (const char *version)
- {
- begin_s_expr ("version");
- write_state_a_string (version);
- end_s_expr ();
- }
- /* Write a scalar type. We have only two of these. */
- void
- state_writer::write_state_scalar_type (type_p current)
- {
- write_any_indent (0);
- if (current == &scalar_nonchar)
- fprintf (state_file, "scalar_nonchar ");
- else if (current == &scalar_char)
- fprintf (state_file, "scalar_char ");
- else
- fatal ("Unexpected type in write_state_scalar_type");
- write_state_common_type_content (current);
- }
- /* Write the string type. There is only one such thing! */
- void
- state_writer::write_state_string_type (type_p current)
- {
- if (current == &string_type)
- {
- write_any_indent (0);
- fprintf (state_file, "string ");
- write_state_common_type_content (current);
- }
- else
- fatal ("Unexpected type in write_state_string_type");
- }
- /* Write an undefined type. */
- void
- state_writer::write_state_undefined_type (type_p current)
- {
- DBGPRINTF ("undefined type @ %p #%d '%s'", (void *) current,
- current->state_number, current->u.s.tag);
- write_any_indent (0);
- fprintf (state_file, "undefined ");
- gcc_assert (current->gc_used == GC_UNUSED);
- write_state_common_type_content (current);
- if (current->u.s.tag != NULL)
- write_state_a_string (current->u.s.tag);
- else
- {
- write_any_indent (0);
- fprintf (state_file, "nil");
- }
- write_state_fileloc (type_lineloc (current));
- }
- /* Common code to write structure like types. */
- void
- state_writer::write_state_struct_union_type (type_p current,
- const char *kindstr)
- {
- DBGPRINTF ("%s type @ %p #%d '%s'", kindstr, (void *) current,
- current->state_number, current->u.s.tag);
- write_any_indent (0);
- fprintf (state_file, "%s ", kindstr);
- write_state_common_type_content (current);
- if (current->u.s.tag != NULL)
- write_state_a_string (current->u.s.tag);
- else
- {
- write_any_indent (0);
- fprintf (state_file, "nil");
- }
- write_state_fileloc (type_lineloc (current));
- write_state_fields (current->u.s.fields);
- write_state_options (current->u.s.opt);
- write_state_lang_bitmap (current->u.s.bitmap);
- }
- /* Write a GTY struct type. */
- void
- state_writer::write_state_struct_type (type_p current)
- {
- write_state_struct_union_type (current, "struct");
- write_state_type (current->u.s.lang_struct);
- write_state_type (current->u.s.base_class);
- }
- /* Write a GTY user-defined struct type. */
- void
- state_writer::write_state_user_struct_type (type_p current)
- {
- DBGPRINTF ("user_struct type @ %p #%d '%s'", (void *) current,
- current->state_number, current->u.s.tag);
- write_any_indent (0);
- fprintf (state_file, "user_struct ");
- write_state_common_type_content (current);
- if (current->u.s.tag != NULL)
- write_state_a_string (current->u.s.tag);
- else
- {
- write_any_indent (0);
- fprintf (state_file, "nil");
- }
- write_state_fileloc (type_lineloc (current));
- write_state_fields (current->u.s.fields);
- }
- /* write a GTY union type. */
- void
- state_writer::write_state_union_type (type_p current)
- {
- write_state_struct_union_type (current, "union");
- write_state_type (current->u.s.lang_struct);
- }
- /* Write a lang_struct type. This is tricky and was painful to debug,
- we deal with the next field specifically within their lang_struct
- subfield, which points to a linked list of homonumous types.
- Change this function with extreme care, see also
- read_state_lang_struct_type. */
- void
- state_writer::write_state_lang_struct_type (type_p current)
- {
- int nbhomontype = 0;
- type_p hty = NULL;
- const char *homoname = 0;
- write_state_struct_union_type (current, "lang_struct");
- /* lang_struct-ures are particularly tricky, since their
- u.s.lang_struct field gives a list of homonymous struct-s or
- union-s! */
- DBGPRINTF ("lang_struct @ %p #%d", (void *) current, current->state_number);
- for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
- {
- nbhomontype++;
- DBGPRINTF ("homonymous #%d hty @ %p #%d '%s'", nbhomontype,
- (void *) hty, hty->state_number, hty->u.s.tag);
- /* Every member of the homonymous list should have the same tag. */
- gcc_assert (union_or_struct_p (hty));
- gcc_assert (hty->u.s.lang_struct == current);
- if (!homoname)
- homoname = hty->u.s.tag;
- gcc_assert (strcmp (homoname, hty->u.s.tag) == 0);
- }
- begin_s_expr ("homotypes");
- fprintf (state_file, "%d", nbhomontype);
- for (hty = current->u.s.lang_struct; hty != NULL; hty = hty->next)
- write_state_type (hty);
- end_s_expr ();
- }
- /* Write a pointer type. */
- void
- state_writer::write_state_pointer_type (type_p current)
- {
- write_any_indent (0);
- fprintf (state_file, "pointer ");
- write_state_common_type_content (current);
- write_state_type (current->u.p);
- }
- /* Write an array type. */
- void
- state_writer::write_state_array_type (type_p current)
- {
- write_any_indent (0);
- fprintf (state_file, "array ");
- write_state_common_type_content (current);
- if (current->u.a.len != NULL)
- write_state_a_string (current->u.a.len);
- else
- {
- write_any_indent (1);
- fprintf (state_file, " nil");
- }
- write_any_indent (1);
- fprintf (state_file, " ");
- write_state_type (current->u.a.p);
- }
- /* Write the gc_used information. */
- void
- state_writer::write_state_gc_used (enum gc_used_enum gus)
- {
- write_any_indent (1);
- switch (gus)
- {
- case GC_UNUSED:
- fprintf (state_file, " gc_unused");
- break;
- case GC_USED:
- fprintf (state_file, " gc_used");
- break;
- case GC_MAYBE_POINTED_TO:
- fprintf (state_file, " gc_maybe_pointed_to");
- break;
- case GC_POINTED_TO:
- fprintf (state_file, " gc_pointed_to");
- break;
- default:
- gcc_unreachable ();
- }
- }
- /* Utility routine to write the common content of all types. Notice
- that the next field is *not* written on purpose. */
- void
- state_writer::write_state_common_type_content (type_p current)
- {
- write_any_indent (0);
- fprintf (state_file, "%d ", current->state_number);
- /* We do not write the next type, because list of types are
- explicitly written. However, lang_struct are special in that
- respect. See function write_state_lang_struct_type for more. */
- write_state_type (current->pointer_to);
- write_state_gc_used (current->gc_used);
- }
- /* The important and recursive routine writing GTY types as understood
- by gengtype. Types which have a positive state_number have already
- been seen and written. */
- void
- state_writer::write_state_type (type_p current)
- {
- write_any_indent (0);
- if (current == NULL)
- {
- fprintf (state_file, "nil ");
- return;
- }
- begin_s_expr ("type");
- if (current->state_number > 0)
- {
- write_any_indent (0);
- fprintf (state_file, "already_seen %d", current->state_number);
- }
- else
- {
- m_state_written_type_count++;
- DBGPRINTF ("writing type #%d @%p old number %d", m_state_written_type_count,
- (void *) current, current->state_number);
- current->state_number = m_state_written_type_count;
- switch (current->kind)
- {
- case TYPE_NONE:
- gcc_unreachable ();
- case TYPE_UNDEFINED:
- write_state_undefined_type (current);
- break;
- case TYPE_STRUCT:
- write_state_struct_type (current);
- break;
- case TYPE_USER_STRUCT:
- write_state_user_struct_type (current);
- break;
- case TYPE_UNION:
- write_state_union_type (current);
- break;
- case TYPE_POINTER:
- write_state_pointer_type (current);
- break;
- case TYPE_ARRAY:
- write_state_array_type (current);
- break;
- case TYPE_LANG_STRUCT:
- write_state_lang_struct_type (current);
- break;
- case TYPE_SCALAR:
- write_state_scalar_type (current);
- break;
- case TYPE_STRING:
- write_state_string_type (current);
- break;
- }
- }
- /* Terminate the "type" s-expression. */
- end_s_expr ();
- }
- /* Write a pair. */
- void
- state_writer::write_state_pair (pair_p current)
- {
- if (current == NULL)
- {
- write_any_indent (0);
- fprintf (state_file, "nil)");
- return;
- }
- begin_s_expr ("pair");
- if (current->name != NULL)
- write_state_a_string (current->name);
- else
- write_state_a_string ("nil");
- write_state_type (current->type);
- write_state_fileloc (&(current->line));
- write_state_options (current->opt);
- /* Terminate the "pair" s-expression. */
- end_s_expr ();
- }
- /* Write a pair list and return the number of pairs written. */
- int
- state_writer::write_state_pair_list (pair_p list)
- {
- int nbpair = 0;
- pair_p current;
- for (current = list; current != NULL; current = current->next)
- {
- write_state_pair (current);
- nbpair++;
- }
- return nbpair;
- }
- /* When writing imported linked lists, like typedefs, structures, ... we count
- their length first and write it. This eases the reading, and enables an
- extra verification on the number of actually read items. */
- /* Write our typedefs. */
- void
- state_writer::write_state_typedefs (void)
- {
- int nbtypedefs = pair_list_length (typedefs);
- int nbpairs = 0;
- begin_s_expr ("typedefs");
- fprintf (state_file, "%d", nbtypedefs);
- nbpairs = write_state_pair_list (typedefs);
- gcc_assert (nbpairs == nbtypedefs);
- end_s_expr ();
- if (verbosity_level >= 2)
- printf ("%s wrote %d typedefs\n", progname, nbtypedefs);
- }
- /* Write our structures. */
- void
- state_writer::write_state_structures (void)
- {
- int nbstruct = 0;
- type_p current;
- for (current = structures; current != NULL; current = current->next)
- nbstruct++;
- begin_s_expr ("structures");
- fprintf (state_file, "%d", nbstruct);
- for (current = structures; current != NULL; current = current->next)
- {
- write_new_line ();
- write_state_type (current);
- }
- /* Terminate the "structures" s-expression. */
- end_s_expr ();
- if (verbosity_level >= 2)
- printf ("%s wrote %d structures in state\n", progname, nbstruct);
- }
- /* Write our variables. */
- void
- state_writer::write_state_variables (void)
- {
- int nbvars = pair_list_length (variables);
- int nbpairs = 0;
- begin_s_expr ("variables");
- fprintf (state_file, "%d", nbvars);
- nbpairs = write_state_pair_list (variables);
- gcc_assert (nbpairs == nbvars);
- end_s_expr ();
- if (verbosity_level >= 2)
- printf ("%s wrote %d variables.\n", progname, nbvars);
- }
- /* Write the source directory. File locations within the source
- directory have been written specifically. */
- void
- state_writer::write_state_srcdir (void)
- {
- begin_s_expr ("srcdir");
- write_state_a_string (srcdir);
- end_s_expr ();
- }
- /* Count and write the list of our files. */
- void
- state_writer::write_state_files_list (void)
- {
- int i = 0;
- /* Write the list of files with their lang_bitmap. */
- begin_s_expr ("fileslist");
- fprintf (state_file, "%d", (int) num_gt_files);
- for (i = 0; i < (int) num_gt_files; i++)
- {
- const char *cursrcrelpath = NULL;
- const input_file *curfil = gt_files[i];
- /* Most of the files are inside $(srcdir) so it is worth to
- handle them specially. */
- cursrcrelpath = get_file_srcdir_relative_path (curfil);
- if (cursrcrelpath)
- {
- begin_s_expr ("srcfile");
- fprintf (state_file, "%d ", get_lang_bitmap (curfil));
- write_state_a_string (cursrcrelpath);
- }
- else
- {
- begin_s_expr ("file");
- fprintf (state_file, "%d ", get_lang_bitmap (curfil));
- write_state_a_string (get_input_file_name (curfil));
- }
- /* Terminate the inner s-expression (either "srcfile" or "file"). */
- end_s_expr ();
- }
- /* Terminate the "fileslist" s-expression. */
- end_s_expr ();
- }
- /* Write the list of GCC front-end languages. */
- void
- state_writer::write_state_languages (void)
- {
- int i = 0;
- begin_s_expr ("languages");
- fprintf (state_file, "%d", (int) num_lang_dirs);
- for (i = 0; i < (int) num_lang_dirs; i++)
- {
- /* Languages names are identifiers, we expect only letters or
- underscores or digits in them. In particular, C++ is not a
- valid language name, but cp is valid. */
- fprintf (state_file, " %s", lang_dir_names[i]);
- }
- end_s_expr ();
- }
- /* Write the trailer. */
- static void
- write_state_trailer (void)
- {
- /* This test should probably catch IO errors like disk full... */
- if (fputs ("\n(!endfile)\n", state_file) == EOF)
- fatal ("failed to write state trailer [%s]", xstrerror (errno));
- }
- /* The write_state routine is the only writing routine called by main
- in gengtype.c. To avoid messing the state if gengtype is
- interrupted or aborted, we write a temporary file and rename it
- after having written it in totality. */
- void
- write_state (const char *state_path)
- {
- long statelen = 0;
- time_t now = 0;
- char *temp_state_path = NULL;
- char tempsuffix[40];
- time (&now);
- /* We write a unique temporary file which is renamed when complete
- * only. So even if gengtype is interrupted, the written state file
- * won't be partially written, since the temporary file is not yet
- * renamed in that case. */
- memset (tempsuffix, 0, sizeof (tempsuffix));
- snprintf (tempsuffix, sizeof (tempsuffix) - 1, "-%ld-%d.tmp", (long) now,
- (int) getpid ());
- temp_state_path = concat (state_path, tempsuffix, NULL);
- state_file = fopen (temp_state_path, "w");
- if (state_file == NULL)
- fatal ("Failed to open file %s for writing state: %s",
- temp_state_path, xstrerror (errno));
- if (verbosity_level >= 3)
- printf ("%s writing state file %s temporarily in %s\n",
- progname, state_path, temp_state_path);
- /* This is the first line of the state. Perhaps the file utility
- could know about that, so don't change it often. */
- fprintf (state_file, ";;;;@@@@ GCC gengtype state\n");
- /* Output a few comments for humans. */
- fprintf (state_file,
- ";;; DON'T EDIT THIS FILE, since generated by GCC's gengtype\n");
- fprintf (state_file,
- ";;; The format of this file is tied to a particular version of GCC.\n");
- fprintf (state_file,
- ";;; Don't parse this file wihout knowing GCC gengtype internals.\n");
- fprintf (state_file,
- ";;; This file should be parsed by the same %s which wrote it.\n",
- progname);
- state_writer sw;
- /* The first non-comment significant line gives the version string. */
- sw.write_state_version (version_string);
- sw.write_state_srcdir ();
- sw.write_state_languages ();
- sw.write_state_files_list ();
- sw.write_state_structures ();
- sw.write_state_typedefs ();
- sw.write_state_variables ();
- write_state_trailer ();
- statelen = ftell (state_file);
- if (ferror (state_file))
- fatal ("output error when writing state file %s [%s]",
- temp_state_path, xstrerror (errno));
- if (fclose (state_file))
- fatal ("failed to close state file %s [%s]",
- temp_state_path, xstrerror (errno));
- if (rename (temp_state_path, state_path))
- fatal ("failed to rename %s to state file %s [%s]", temp_state_path,
- state_path, xstrerror (errno));
- free (temp_state_path);
- if (verbosity_level >= 1)
- printf ("%s wrote state file %s of %ld bytes with %d GTY-ed types\n",
- progname, state_path, statelen, sw.m_state_written_type_count);
- }
- /** End of writing routines! The corresponding reading routines follow. **/
- /* Forward declarations, since some read_state_* functions are
- recursive! */
- static void read_state_fileloc (struct fileloc *line);
- static void read_state_options (options_p *opt);
- static void read_state_type (type_p *current);
- static void read_state_pair (pair_p *pair);
- /* Return the number of pairs actually read. */
- static int read_state_pair_list (pair_p *list);
- static void read_state_fields (pair_p *fields);
- static void read_state_common_type_content (type_p current);
- /* Record into the state_seen_types hash-table a type which we are
- reading, to enable recursive or circular references to it. */
- static void
- record_type (type_p type)
- {
- PTR *slot;
- slot = htab_find_slot (state_seen_types, type, INSERT);
- gcc_assert (slot);
- *slot = type;
- }
- /* Read an already seen type. */
- static void
- read_state_already_seen_type (type_p *type)
- {
- struct state_token_st *t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_INTEGER)
- {
- PTR *slot = NULL;
- struct type loctype = { TYPE_SCALAR, 0, 0, 0, GC_UNUSED, {0} };
- loctype.state_number = t0->stok_un.stok_num;
- slot = htab_find_slot (state_seen_types, &loctype, NO_INSERT);
- if (slot == NULL)
- {
- fatal_reading_state (t0, "Unknown type");
- }
- next_state_tokens (1);
- *type = (type_p) *slot;
- }
- else
- {
- fatal_reading_state (t0, "Bad seen type");
- }
- }
- /* Read the scalar_nonchar type. */
- static void
- read_state_scalar_nonchar_type (type_p *type)
- {
- *type = &scalar_nonchar;
- read_state_common_type_content (*type);
- }
- /* Read the scalar_char type. */
- static void
- read_state_scalar_char_type (type_p *type)
- {
- *type = &scalar_char;
- read_state_common_type_content (*type);
- }
- /* Read the string_type. */
- static void
- read_state_string_type (type_p *type)
- {
- *type = &string_type;
- read_state_common_type_content (*type);
- }
- /* Read a lang_bitmap representing a set of GCC front-end languages. */
- static void
- read_state_lang_bitmap (lang_bitmap *bitmap)
- {
- struct state_token_st *t;
- t = peek_state_token (0);
- if (state_token_kind (t) == STOK_INTEGER)
- {
- *bitmap = t->stok_un.stok_num;
- next_state_tokens (1);
- }
- else
- {
- fatal_reading_state (t, "Bad syntax for bitmap");
- }
- }
- /* Read an undefined type. */
- static void
- read_state_undefined_type (type_p type)
- {
- struct state_token_st *t0;
- type->kind = TYPE_UNDEFINED;
- read_state_common_type_content (type);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- if (state_token_is_name (t0, "nil"))
- {
- type->u.s.tag = NULL;
- DBGPRINTF ("read anonymous undefined type @%p #%d",
- (void *) type, type->state_number);
- }
- else
- {
- type->u.s.tag = xstrdup (t0->stok_un.stok_string);
- DBGPRINTF ("read undefined type @%p #%d '%s'",
- (void *) type, type->state_number, type->u.s.tag);
- }
- next_state_tokens (1);
- read_state_fileloc (&(type->u.s.line));
- }
- else
- {
- fatal_reading_state (t0, "Bad tag in undefined type");
- }
- }
- /* Read a GTY-ed struct type. */
- static void
- read_state_struct_type (type_p type)
- {
- struct state_token_st *t0;
- type->kind = TYPE_STRUCT;
- read_state_common_type_content (type);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- if (state_token_is_name (t0, "nil"))
- {
- type->u.s.tag = NULL;
- DBGPRINTF ("read anonymous struct type @%p #%d",
- (void *) type, type->state_number);
- }
- else
- {
- type->u.s.tag = xstrdup (t0->stok_un.stok_string);
- DBGPRINTF ("read struct type @%p #%d '%s'",
- (void *) type, type->state_number, type->u.s.tag);
- }
- next_state_tokens (1);
- read_state_fileloc (&(type->u.s.line));
- read_state_fields (&(type->u.s.fields));
- read_state_options (&(type->u.s.opt));
- read_state_lang_bitmap (&(type->u.s.bitmap));
- read_state_type (&(type->u.s.lang_struct));
- read_state_type (&(type->u.s.base_class));
- if (type->u.s.base_class)
- add_subclass (type->u.s.base_class, type);
- }
- else
- {
- fatal_reading_state (t0, "Bad tag in struct type");
- }
- }
- /* Read a GTY-ed user-provided struct TYPE. */
- static void
- read_state_user_struct_type (type_p type)
- {
- struct state_token_st *t0;
- type->kind = TYPE_USER_STRUCT;
- read_state_common_type_content (type);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- if (state_token_is_name (t0, "nil"))
- {
- type->u.s.tag = NULL;
- DBGPRINTF ("read anonymous struct type @%p #%d",
- (void *) type, type->state_number);
- }
- else
- {
- type->u.s.tag = xstrdup (t0->stok_un.stok_string);
- DBGPRINTF ("read struct type @%p #%d '%s'",
- (void *) type, type->state_number, type->u.s.tag);
- }
- next_state_tokens (1);
- read_state_fileloc (&(type->u.s.line));
- read_state_fields (&(type->u.s.fields));
- }
- else
- {
- fatal_reading_state (t0, "Bad tag in user-struct type");
- }
- }
- /* Read a GTY-ed union type. */
- static void
- read_state_union_type (type_p type)
- {
- struct state_token_st *t0;
- type->kind = TYPE_UNION;
- read_state_common_type_content (type);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- if (state_token_is_name (t0, "nil"))
- {
- type->u.s.tag = NULL;
- DBGPRINTF ("read anonymous union type @%p #%d",
- (void *) type, type->state_number);
- }
- else
- {
- type->u.s.tag = xstrdup (t0->stok_un.stok_string);
- DBGPRINTF ("read union type @%p #%d '%s'",
- (void *) type, type->state_number, type->u.s.tag);
- }
- next_state_tokens (1);
- read_state_fileloc (&(type->u.s.line));
- read_state_fields (&(type->u.s.fields));
- read_state_options (&(type->u.s.opt));
- read_state_lang_bitmap (&(type->u.s.bitmap));
- read_state_type (&(type->u.s.lang_struct));
- }
- else
- fatal_reading_state (t0, "Bad tag in union type");
- }
- /* Read a GTY-ed pointer type. */
- static void
- read_state_pointer_type (type_p type)
- {
- type->kind = TYPE_POINTER;
- read_state_common_type_content (type);
- DBGPRINTF ("read pointer type @%p #%d", (void *) type, type->state_number);
- read_state_type (&(type->u.p));
- }
- /* Read a GTY-ed array type. */
- static void
- read_state_array_type (type_p type)
- {
- struct state_token_st *t0;
- type->kind = TYPE_ARRAY;
- read_state_common_type_content (type);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- type->u.a.len = xstrdup (t0->stok_un.stok_string);
- DBGPRINTF ("read array type @%p #%d length '%s'",
- (void *) type, type->state_number, type->u.a.len);
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- type->u.a.len = NULL;
- DBGPRINTF ("read array type @%p #%d without length",
- (void *) type, type->state_number);
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad array name type");
- read_state_type (&(type->u.a.p));
- }
- /* Read a lang_struct type for GTY-ed struct-s which depends upon GCC
- front-end languages. This is a tricky function and it was painful
- to debug. Change it with extreme care. See also
- write_state_lang_struct_type. */
- static void
- read_state_lang_struct_type (type_p type)
- {
- struct state_token_st *t0 = NULL;
- struct state_token_st *t1 = NULL;
- struct state_token_st *t2 = NULL;
- type->kind = TYPE_LANG_STRUCT;
- read_state_common_type_content (type);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- if (state_token_is_name (t0, "nil"))
- {
- DBGPRINTF ("read anonymous lang_struct type @%p #%d",
- (void *) type, type->state_number);
- type->u.s.tag = NULL;
- }
- else
- {
- type->u.s.tag = xstrdup (t0->stok_un.stok_string);
- DBGPRINTF ("read lang_struct type @%p #%d '%s'",
- (void *) type, type->state_number, type->u.s.tag);
- }
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad tag in lang struct type");
- read_state_fileloc (&(type->u.s.line));
- read_state_fields (&(type->u.s.fields));
- read_state_options (&(type->u.s.opt));
- read_state_lang_bitmap (&(type->u.s.bitmap));
- /* Within lang_struct-ures, the lang_struct field is a linked list
- of homonymous types! */
- t0 = peek_state_token (0);
- t1 = peek_state_token (1);
- t2 = peek_state_token (2);
- /* Parse (!homotypes <number-types> <type-1> .... <type-n>) */
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!homotypes")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- type_p *prevty = &type->u.s.lang_struct;
- int nbhomotype = t2->stok_un.stok_num;
- int i = 0;
- t0 = t1 = t2 = NULL;
- next_state_tokens (3);
- for (i = 0; i < nbhomotype; i++)
- {
- read_state_type (prevty);
- t0 = peek_state_token (0);
- if (*prevty)
- prevty = &(*prevty)->next;
- else
- fatal_reading_state (t0,
- "expecting type in homotype list for lang_struct");
- };
- if (state_token_kind (t0) != STOK_RIGHTPAR)
- fatal_reading_state (t0,
- "expecting ) in homotype list for lang_struct");
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "expecting !homotypes for lang_struct");
- }
- /* Read the gc used information. */
- static void
- read_state_gc_used (enum gc_used_enum *pgus)
- {
- struct state_token_st *t0 = peek_state_token (0);
- if (state_token_is_name (t0, "gc_unused"))
- *pgus = GC_UNUSED;
- else if (state_token_is_name (t0, "gc_used"))
- *pgus = GC_USED;
- else if (state_token_is_name (t0, "gc_maybe_pointed_to"))
- *pgus = GC_MAYBE_POINTED_TO;
- else if (state_token_is_name (t0, "gc_pointed_to"))
- *pgus = GC_POINTED_TO;
- else
- fatal_reading_state (t0, "invalid gc_used information");
- next_state_tokens (1);
- }
- /* Utility function to read the common content of types. */
- static void
- read_state_common_type_content (type_p current)
- {
- struct state_token_st *t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_INTEGER)
- {
- current->state_number = t0->stok_un.stok_num;
- next_state_tokens (1);
- record_type (current);
- }
- else
- fatal_reading_state_printf (t0,
- "Expected integer for state_number line %d",
- state_line);
- /* We don't read the next field of the type. */
- read_state_type (¤t->pointer_to);
- read_state_gc_used (¤t->gc_used);
- }
- /* Read a GTY-ed type. */
- void
- read_state_type (type_p *current)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- state_token_is_name (t1, "!type"))
- {
- next_state_tokens (2);
- t0 = peek_state_token (0);
- if (state_token_is_name (t0, "already_seen"))
- {
- next_state_tokens (1);
- read_state_already_seen_type (current);
- }
- else
- {
- t0 = peek_state_token (0);
- if (state_token_is_name (t0, "scalar_nonchar"))
- {
- next_state_tokens (1);
- read_state_scalar_nonchar_type (current);
- }
- else if (state_token_is_name (t0, "scalar_char"))
- {
- next_state_tokens (1);
- read_state_scalar_char_type (current);
- }
- else if (state_token_is_name (t0, "string"))
- {
- next_state_tokens (1);
- read_state_string_type (current);
- }
- else if (state_token_is_name (t0, "undefined"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_undefined_type (*current);
- }
- else if (state_token_is_name (t0, "struct"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_struct_type (*current);
- }
- else if (state_token_is_name (t0, "union"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_union_type (*current);
- }
- else if (state_token_is_name (t0, "lang_struct"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_lang_struct_type (*current);
- }
- else if (state_token_is_name (t0, "pointer"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_pointer_type (*current);
- }
- else if (state_token_is_name (t0, "array"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_array_type (*current);
- }
- else if (state_token_is_name (t0, "user_struct"))
- {
- *current = XCNEW (struct type);
- next_state_tokens (1);
- read_state_user_struct_type (*current);
- }
- else
- fatal_reading_state (t0, "bad type in (!type");
- }
- t0 = peek_state_token (0);
- if (state_token_kind (t0) != STOK_RIGHTPAR)
- fatal_reading_state (t0, "missing ) in type");
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- next_state_tokens (1);
- *current = NULL;
- }
- else
- fatal_reading_state (t0, "bad type syntax");
- }
- /* Read a file location. Files within the source directory are dealt
- with specifically. */
- void
- read_state_fileloc (struct fileloc *floc)
- {
- bool issrcfile = false;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- gcc_assert (floc != NULL);
- gcc_assert (srcdir != NULL);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- (state_token_is_name (t1, "!fileloc")
- || (issrcfile = state_token_is_name (t1, "!srcfileloc"))))
- {
- next_state_tokens (2);
- t0 = peek_state_token (0);
- t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_STRING &&
- state_token_kind (t1) == STOK_INTEGER)
- {
- char *path = t0->stok_un.stok_string;
- if (issrcfile)
- {
- static const char dirsepstr[2] = { DIR_SEPARATOR, (char) 0 };
- char *fullpath = concat (srcdir, dirsepstr, path, NULL);
- floc->file = input_file_by_name (fullpath);
- free (fullpath);
- }
- else
- floc->file = input_file_by_name (path);
- floc->line = t1->stok_un.stok_num;
- next_state_tokens (2);
- }
- else
- fatal_reading_state (t0,
- "Bad fileloc syntax, expected path string and line");
- t0 = peek_state_token (0);
- if (state_token_kind (t0) != STOK_RIGHTPAR)
- fatal_reading_state (t0, "Bad fileloc syntax, expected )");
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- next_state_tokens (1);
- floc->file = NULL;
- floc->line = 0;
- }
- else
- fatal_reading_state (t0, "Bad fileloc syntax");
- }
- /* Read the fields of a GTY-ed type. */
- void
- read_state_fields (pair_p *fields)
- {
- pair_p tmp = NULL;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!fields")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- int nbfields = t2->stok_un.stok_num;
- int nbpairs = 0;
- next_state_tokens (3);
- nbpairs = read_state_pair_list (&tmp);
- t0 = peek_state_token (0);
- if (nbpairs != nbfields)
- fatal_reading_state_printf
- (t0,
- "Mismatched fields number, expected %d got %d", nbpairs, nbfields);
- if (state_token_kind (t0) == STOK_RIGHTPAR)
- next_state_tokens (1);
- else
- fatal_reading_state (t0, "Bad fields expecting )");
- }
- *fields = tmp;
- }
- /* Read a string option. */
- static void
- read_state_string_option (options_p opt)
- {
- struct state_token_st *t0 = peek_state_token (0);
- opt->kind = OPTION_STRING;
- if (state_token_kind (t0) == STOK_STRING)
- {
- opt->info.string = xstrdup (t0->stok_un.stok_string);
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- opt->info.string = NULL;
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Missing name in string option");
- }
- /* Read a type option. */
- static void
- read_state_type_option (options_p opt)
- {
- opt->kind = OPTION_TYPE;
- read_state_type (&(opt->info.type));
- }
- /* Read a nested option. */
- static void
- read_state_nested_option (options_p opt)
- {
- struct state_token_st *t0;
- opt->info.nested = XCNEW (struct nested_ptr_data);
- opt->kind = OPTION_NESTED;
- read_state_type (&(opt->info.nested->type));
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- opt->info.nested->convert_from = xstrdup (t0->stok_un.stok_string);
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- opt->info.nested->convert_from = NULL;
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad nested convert_from option");
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- opt->info.nested->convert_to = xstrdup (t0->stok_un.stok_string);
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- opt->info.nested->convert_to = NULL;
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad nested convert_from option");
- }
- /* Read an GTY option. */
- static void
- read_state_option (options_p *opt)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- state_token_is_name (t1, "!option"))
- {
- next_state_tokens (2);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_NAME)
- {
- *opt = XCNEW (struct options);
- if (state_token_is_name (t0, "nil"))
- (*opt)->name = NULL;
- else
- (*opt)->name = t0->stok_un.stok_ident->stid_name;
- next_state_tokens (1);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_NAME)
- {
- if (state_token_is_name (t0, "string"))
- {
- next_state_tokens (1);
- read_state_string_option (*opt);
- }
- else if (state_token_is_name (t0, "type"))
- {
- next_state_tokens (1);
- read_state_type_option (*opt);
- }
- else if (state_token_is_name (t0, "nested"))
- {
- next_state_tokens (1);
- read_state_nested_option (*opt);
- }
- else
- fatal_reading_state (t0, "Bad option type");
- t0 = peek_state_token (0);
- if (state_token_kind (t0) != STOK_RIGHTPAR)
- fatal_reading_state (t0, "Bad syntax in option, expecting )");
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Missing option type");
- }
- else
- fatal_reading_state (t0, "Bad name for option");
- }
- else
- fatal_reading_state (t0, "Bad option, waiting for )");
- }
- /* Read a list of options. */
- void
- read_state_options (options_p *opt)
- {
- options_p head = NULL;
- options_p previous = NULL;
- options_p current_option = NULL;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- state_token_is_name (t1, "!options"))
- {
- next_state_tokens (2);
- t0 = peek_state_token (0);
- while (state_token_kind (t0) != STOK_RIGHTPAR)
- {
- read_state_option (¤t_option);
- if (head == NULL)
- {
- head = current_option;
- previous = head;
- }
- else
- {
- previous->next = current_option;
- previous = current_option;
- }
- t0 = peek_state_token (0);
- }
- next_state_tokens (1);
- }
- else if (state_token_is_name (t0, "nil"))
- {
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad options syntax");
- *opt = head;
- }
- /* Read a version, and check against the version of the gengtype. */
- static void
- read_state_version (const char *version_string)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- state_token_is_name (t1, "!version"))
- {
- next_state_tokens (2);
- t0 = peek_state_token (0);
- t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_STRING &&
- state_token_kind (t1) == STOK_RIGHTPAR)
- {
- /* Check that the read version string is the same as current
- version. */
- if (strcmp (version_string, t0->stok_un.stok_string))
- fatal_reading_state_printf (t0,
- "version string mismatch; expecting %s but got %s",
- version_string,
- t0->stok_un.stok_string);
- next_state_tokens (2);
- }
- else
- fatal_reading_state (t0, "Missing version or right parenthesis");
- }
- else
- fatal_reading_state (t0, "Bad version syntax");
- }
- /* Read a pair. */
- void
- read_state_pair (pair_p *current)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- state_token_is_name (t1, "!pair"))
- {
- *current = XCNEW (struct pair);
- next_state_tokens (2);
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_STRING)
- {
- if (strcmp (t0->stok_un.stok_string, "nil") == 0)
- {
- (*current)->name = NULL;
- }
- else
- {
- (*current)->name = xstrdup (t0->stok_un.stok_string);
- }
- next_state_tokens (1);
- read_state_type (&((*current)->type));
- read_state_fileloc (&((*current)->line));
- read_state_options (&((*current)->opt));;
- t0 = peek_state_token (0);
- if (state_token_kind (t0) == STOK_RIGHTPAR)
- {
- next_state_tokens (1);
- }
- else
- {
- fatal_reading_state (t0, "Bad syntax for pair, )");
- }
- }
- else
- {
- fatal_reading_state (t0, "Bad name for pair");
- }
- }
- else if (state_token_kind (t0) == STOK_NAME &&
- state_token_is_name (t0, "nil"))
- {
- next_state_tokens (1);
- *current = NULL;
- }
- else
- fatal_reading_state_printf (t0, "Bad syntax for pair, (!pair %d",
- state_token->stok_kind);
- }
- /* Return the number of pairs actually read. */
- int
- read_state_pair_list (pair_p *list)
- {
- int nbpair = 0;
- pair_p head = NULL;
- pair_p previous = NULL;
- pair_p tmp = NULL;
- struct state_token_st *t0 = peek_state_token (0);
- while (t0 && state_token_kind (t0) != STOK_RIGHTPAR)
- {
- read_state_pair (&tmp);
- if (head == NULL)
- {
- head = tmp;
- previous = head;
- }
- else
- {
- previous->next = tmp;
- previous = tmp;
- }
- t0 = peek_state_token (0);
- nbpair++;
- }
- /* don't consume the ); the caller will eat it. */
- *list = head;
- return nbpair;
- }
- /* Read the typedefs. */
- static void
- read_state_typedefs (pair_p *typedefs)
- {
- int nbtypedefs = 0;
- pair_p list = NULL;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!typedefs")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- int nbpairs = 0;
- nbtypedefs = t2->stok_un.stok_num;
- next_state_tokens (3);
- nbpairs = read_state_pair_list (&list);
- t0 = peek_state_token (0);
- if (nbpairs != nbtypedefs)
- fatal_reading_state_printf
- (t0,
- "invalid number of typedefs, expected %d but got %d",
- nbtypedefs, nbpairs);
- if (state_token_kind (t0) == STOK_RIGHTPAR)
- next_state_tokens (1);
- else
- fatal_reading_state (t0, "Bad typedefs syntax )");
- }
- else
- fatal_reading_state (t0, "Bad typedefs syntax (!typedefs");
- if (verbosity_level >= 2)
- printf ("%s read %d typedefs from state\n", progname, nbtypedefs);
- *typedefs = list;
- }
- /* Read the structures. */
- static void
- read_state_structures (type_p *structures)
- {
- type_p head = NULL;
- type_p previous = NULL;
- type_p tmp;
- int nbstruct = 0, countstruct = 0;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!structures")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- nbstruct = t2->stok_un.stok_num;
- next_state_tokens (3);
- t0 = peek_state_token (0);
- while (t0 && state_token_kind (t0) != STOK_RIGHTPAR)
- {
- tmp = NULL;
- read_state_type (&tmp);
- countstruct++;
- if (head == NULL)
- {
- head = tmp;
- previous = head;
- }
- else
- {
- previous->next = tmp;
- previous = tmp;
- }
- t0 = peek_state_token (0);
- }
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "Bad structures syntax");
- if (countstruct != nbstruct)
- fatal_reading_state_printf (NULL_STATE_TOKEN,
- "expected %d structures but got %d",
- nbstruct, countstruct);
- if (verbosity_level >= 2)
- printf ("%s read %d structures from state\n", progname, nbstruct);
- *structures = head;
- }
- /* Read the variables. */
- static void
- read_state_variables (pair_p *variables)
- {
- pair_p list = NULL;
- int nbvars = 0;
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!variables")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- int nbpairs = 0;
- nbvars = t2->stok_un.stok_num;
- next_state_tokens (3);
- nbpairs = read_state_pair_list (&list);
- t0 = peek_state_token (0);
- if (nbpairs != nbvars)
- fatal_reading_state_printf
- (t0, "Invalid number of variables, expected %d but got %d",
- nbvars, nbpairs);
- if (state_token_kind (t0) == STOK_RIGHTPAR)
- next_state_tokens (1);
- else
- fatal_reading_state (t0, "Waiting for ) in variables");
- }
- else
- fatal_reading_state (t0, "Bad variables syntax");
- *variables = list;
- if (verbosity_level >= 2)
- printf ("%s read %d variables from state\n", progname, nbvars);
- }
- /* Read the source directory. */
- static void
- read_state_srcdir (void)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_LEFTPAR &&
- state_token_is_name (t1, "!srcdir"))
- {
- next_state_tokens (2);
- t0 = peek_state_token (0);
- t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_STRING &&
- state_token_kind (t1) == STOK_RIGHTPAR)
- {
- srcdir = xstrdup (t0->stok_un.stok_string);
- srcdir_len = strlen (srcdir);
- next_state_tokens (2);
- return;
- }
- }
- fatal_reading_state (t0, "Bad srcdir in state_file");
- }
- /* Read the sequence of GCC front-end languages. */
- static void
- read_state_languages (void)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!languages")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- int i = 0;
- num_lang_dirs = t2->stok_un.stok_num;
- lang_dir_names = XCNEWVEC (const char *, num_lang_dirs);
- next_state_tokens (3);
- t0 = t1 = t2 = NULL;
- for (i = 0; i < (int) num_lang_dirs; i++)
- {
- t0 = peek_state_token (0);
- if (state_token_kind (t0) != STOK_NAME)
- fatal_reading_state (t0, "expecting language name in state file");
- lang_dir_names[i] = t0->stok_un.stok_ident->stid_name;
- next_state_tokens (1);
- }
- t0 = peek_state_token (0);
- if (state_token_kind (t0) != STOK_RIGHTPAR)
- fatal_reading_state (t0, "missing ) in languages list of state file");
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "expecting languages list in state file");
- }
- /* Read the sequence of files. */
- static void
- read_state_files_list (void)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!fileslist")
- && state_token_kind (t2) == STOK_INTEGER)
- {
- int i = 0;
- num_gt_files = t2->stok_un.stok_num;
- next_state_tokens (3);
- t0 = t1 = t2 = NULL;
- gt_files = XCNEWVEC (const input_file *, num_gt_files);
- for (i = 0; i < (int) num_gt_files; i++)
- {
- bool issrcfile = FALSE;
- t0 = t1 = t2 = NULL;
- t0 = peek_state_token (0);
- t1 = peek_state_token (1);
- t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && (state_token_is_name (t1, "!file")
- || (issrcfile = state_token_is_name (t1, "!srcfile")))
- && state_token_kind (t2) == STOK_INTEGER)
- {
- lang_bitmap bmap = t2->stok_un.stok_num;
- next_state_tokens (3);
- t0 = t1 = t2 = NULL;
- t0 = peek_state_token (0);
- t1 = peek_state_token (1);
- if (state_token_kind (t0) == STOK_STRING
- && state_token_kind (t1) == STOK_RIGHTPAR)
- {
- const char *fnam = t0->stok_un.stok_string;
- /* Allocate & fill a gt_file entry with space for the lang_bitmap before! */
- input_file *curgt = NULL;
- if (issrcfile)
- {
- static const char dirsepstr[2] =
- { DIR_SEPARATOR, (char) 0 };
- char *fullpath = concat (srcdir, dirsepstr, fnam, NULL);
- curgt = input_file_by_name (fullpath);
- free (fullpath);
- }
- else
- curgt = input_file_by_name (fnam);
- set_lang_bitmap (curgt, bmap);
- gt_files[i] = curgt;
- next_state_tokens (2);
- }
- else
- fatal_reading_state (t0,
- "bad file in !fileslist of state file");
- }
- else
- fatal_reading_state (t0,
- "expecting file in !fileslist of state file");
- };
- t0 = peek_state_token (0);
- if (state_token_kind (t0) != STOK_RIGHTPAR)
- fatal_reading_state (t0, "missing ) for !fileslist in state file");
- next_state_tokens (1);
- }
- else
- fatal_reading_state (t0, "missing !fileslist in state file");
- }
- /* Read the trailer. */
- static void
- read_state_trailer (void)
- {
- struct state_token_st *t0 = peek_state_token (0);
- struct state_token_st *t1 = peek_state_token (1);
- struct state_token_st *t2 = peek_state_token (2);
- if (state_token_kind (t0) == STOK_LEFTPAR
- && state_token_is_name (t1, "!endfile")
- && state_token_kind (t2) == STOK_RIGHTPAR)
- next_state_tokens (3);
- else
- fatal_reading_state (t0, "missing !endfile in state file");
- }
- /* Utility functions for the state_seen_types hash table. */
- static unsigned
- hash_type_number (const void *ty)
- {
- const struct type *type = (const struct type *) ty;
- return type->state_number;
- }
- static int
- equals_type_number (const void *ty1, const void *ty2)
- {
- const struct type *type1 = (const struct type *) ty1;
- const struct type *type2 = (const struct type *) ty2;
- return type1->state_number == type2->state_number;
- }
- static int
- string_eq (const void *a, const void *b)
- {
- const char *a0 = (const char *)a;
- const char *b0 = (const char *)b;
- return (strcmp (a0, b0) == 0);
- }
- /* The function reading the state, called by main from gengtype.c. */
- void
- read_state (const char *path)
- {
- state_file = fopen (path, "r");
- if (state_file == NULL)
- fatal ("Failed to open state file %s for reading [%s]", path,
- xstrerror (errno));
- state_path = path;
- state_line = 1;
- if (verbosity_level >= 1)
- {
- printf ("%s reading state file %s;", progname, state_path);
- if (verbosity_level >= 2)
- putchar ('\n');
- fflush (stdout);
- }
- state_seen_types =
- htab_create (2017, hash_type_number, equals_type_number, NULL);
- state_ident_tab =
- htab_create (4027, htab_hash_string, string_eq, NULL);
- read_state_version (version_string);
- read_state_srcdir ();
- read_state_languages ();
- read_state_files_list ();
- read_state_structures (&structures);
- if (ferror (state_file))
- fatal_reading_state_printf
- (NULL_STATE_TOKEN, "input error while reading state [%s]",
- xstrerror (errno));
- read_state_typedefs (&typedefs);
- read_state_variables (&variables);
- read_state_trailer ();
- if (verbosity_level >= 1)
- {
- printf ("%s read %ld bytes.\n", progname, ftell (state_file));
- fflush (stdout);
- };
- if (fclose (state_file))
- fatal ("failed to close read state file %s [%s]",
- path, xstrerror (errno));
- state_file = NULL;
- state_path = NULL;
- }
- /* End of file gengtype-state.c. */
|