1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451 |
- /* Print GENERIC declaration (functions, variables, types) trees coming from
- the C and C++ front-ends as well as macros in Ada syntax.
- Copyright (C) 2010-2015 Free Software Foundation, Inc.
- Adapted from tree-pretty-print.c by Arnaud Charlet <charlet@adacore.com>
- 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/>. */
- #include "config.h"
- #include "system.h"
- #include "coretypes.h"
- #include "tm.h"
- #include "hash-set.h"
- #include "machmode.h"
- #include "vec.h"
- #include "double-int.h"
- #include "input.h"
- #include "alias.h"
- #include "symtab.h"
- #include "options.h"
- #include "wide-int.h"
- #include "inchash.h"
- #include "tree.h"
- #include "fold-const.h"
- #include "dumpfile.h"
- #include "c-ada-spec.h"
- #include "cpplib.h"
- #include "c-pragma.h"
- #include "cpp-id-data.h"
- #include "wide-int.h"
- /* Local functions, macros and variables. */
- static int dump_generic_ada_node (pretty_printer *, tree, tree, int, int,
- bool);
- static int print_ada_declaration (pretty_printer *, tree, tree, int);
- static void print_ada_struct_decl (pretty_printer *, tree, tree, int, bool);
- static void dump_sloc (pretty_printer *buffer, tree node);
- static void print_comment (pretty_printer *, const char *);
- static void print_generic_ada_decl (pretty_printer *, tree, const char *);
- static char *get_ada_package (const char *);
- static void dump_ada_nodes (pretty_printer *, const char *);
- static void reset_ada_withs (void);
- static void dump_ada_withs (FILE *);
- static void dump_ads (const char *, void (*)(const char *),
- int (*)(tree, cpp_operation));
- static char *to_ada_name (const char *, int *);
- static bool separate_class_package (tree);
- #define INDENT(SPACE) \
- do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0)
- #define INDENT_INCR 3
- /* Global hook used to perform C++ queries on nodes. */
- static int (*cpp_check) (tree, cpp_operation) = NULL;
- /* Given a cpp MACRO, compute the max length BUFFER_LEN of the macro, as well
- as max length PARAM_LEN of arguments for fun_like macros, and also set
- SUPPORTED to 0 if the macro cannot be mapped to an Ada construct. */
- static void
- macro_length (const cpp_macro *macro, int *supported, int *buffer_len,
- int *param_len)
- {
- int i;
- unsigned j;
- *supported = 1;
- *buffer_len = 0;
- *param_len = 0;
- if (macro->fun_like)
- {
- param_len++;
- for (i = 0; i < macro->paramc; i++)
- {
- cpp_hashnode *param = macro->params[i];
- *param_len += NODE_LEN (param);
- if (i + 1 < macro->paramc)
- {
- *param_len += 2; /* ", " */
- }
- else if (macro->variadic)
- {
- *supported = 0;
- return;
- }
- }
- *param_len += 2; /* ")\0" */
- }
- for (j = 0; j < macro->count; j++)
- {
- cpp_token *token = ¯o->exp.tokens[j];
- if (token->flags & PREV_WHITE)
- (*buffer_len)++;
- if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
- {
- *supported = 0;
- return;
- }
- if (token->type == CPP_MACRO_ARG)
- *buffer_len +=
- NODE_LEN (macro->params[token->val.macro_arg.arg_no - 1]);
- else
- /* Include enough extra space to handle e.g. special characters. */
- *buffer_len += (cpp_token_len (token) + 1) * 8;
- }
- (*buffer_len)++;
- }
- /* Dump into PP a set of MAX_ADA_MACROS MACROS (C/C++) as Ada constants when
- possible. */
- static void
- print_ada_macros (pretty_printer *pp, cpp_hashnode **macros, int max_ada_macros)
- {
- int j, num_macros = 0, prev_line = -1;
- for (j = 0; j < max_ada_macros; j++)
- {
- cpp_hashnode *node = macros[j];
- const cpp_macro *macro = node->value.macro;
- unsigned i;
- int supported = 1, prev_is_one = 0, buffer_len, param_len;
- int is_string = 0, is_char = 0;
- char *ada_name;
- unsigned char *s, *params, *buffer, *buf_param, *char_one = NULL;
- macro_length (macro, &supported, &buffer_len, ¶m_len);
- s = buffer = XALLOCAVEC (unsigned char, buffer_len);
- params = buf_param = XALLOCAVEC (unsigned char, param_len);
- if (supported)
- {
- if (macro->fun_like)
- {
- *buf_param++ = '(';
- for (i = 0; i < macro->paramc; i++)
- {
- cpp_hashnode *param = macro->params[i];
- memcpy (buf_param, NODE_NAME (param), NODE_LEN (param));
- buf_param += NODE_LEN (param);
- if (i + 1 < macro->paramc)
- {
- *buf_param++ = ',';
- *buf_param++ = ' ';
- }
- else if (macro->variadic)
- {
- supported = 0;
- break;
- }
- }
- *buf_param++ = ')';
- *buf_param = '\0';
- }
- for (i = 0; supported && i < macro->count; i++)
- {
- cpp_token *token = ¯o->exp.tokens[i];
- int is_one = 0;
- if (token->flags & PREV_WHITE)
- *buffer++ = ' ';
- if (token->flags & STRINGIFY_ARG || token->flags & PASTE_LEFT)
- {
- supported = 0;
- break;
- }
- switch (token->type)
- {
- case CPP_MACRO_ARG:
- {
- cpp_hashnode *param =
- macro->params[token->val.macro_arg.arg_no - 1];
- memcpy (buffer, NODE_NAME (param), NODE_LEN (param));
- buffer += NODE_LEN (param);
- }
- break;
- case CPP_EQ_EQ: *buffer++ = '='; break;
- case CPP_GREATER: *buffer++ = '>'; break;
- case CPP_LESS: *buffer++ = '<'; break;
- case CPP_PLUS: *buffer++ = '+'; break;
- case CPP_MINUS: *buffer++ = '-'; break;
- case CPP_MULT: *buffer++ = '*'; break;
- case CPP_DIV: *buffer++ = '/'; break;
- case CPP_COMMA: *buffer++ = ','; break;
- case CPP_OPEN_SQUARE:
- case CPP_OPEN_PAREN: *buffer++ = '('; break;
- case CPP_CLOSE_SQUARE: /* fallthrough */
- case CPP_CLOSE_PAREN: *buffer++ = ')'; break;
- case CPP_DEREF: /* fallthrough */
- case CPP_SCOPE: /* fallthrough */
- case CPP_DOT: *buffer++ = '.'; break;
- case CPP_EQ: *buffer++ = ':'; *buffer++ = '='; break;
- case CPP_NOT_EQ: *buffer++ = '/'; *buffer++ = '='; break;
- case CPP_GREATER_EQ: *buffer++ = '>'; *buffer++ = '='; break;
- case CPP_LESS_EQ: *buffer++ = '<'; *buffer++ = '='; break;
- case CPP_NOT:
- *buffer++ = 'n'; *buffer++ = 'o'; *buffer++ = 't'; break;
- case CPP_MOD:
- *buffer++ = 'm'; *buffer++ = 'o'; *buffer++ = 'd'; break;
- case CPP_AND:
- *buffer++ = 'a'; *buffer++ = 'n'; *buffer++ = 'd'; break;
- case CPP_OR:
- *buffer++ = 'o'; *buffer++ = 'r'; break;
- case CPP_XOR:
- *buffer++ = 'x'; *buffer++ = 'o'; *buffer++ = 'r'; break;
- case CPP_AND_AND:
- strcpy ((char *) buffer, " and then ");
- buffer += 10;
- break;
- case CPP_OR_OR:
- strcpy ((char *) buffer, " or else ");
- buffer += 9;
- break;
- case CPP_PADDING:
- *buffer++ = ' ';
- is_one = prev_is_one;
- break;
- case CPP_COMMENT: break;
- case CPP_WSTRING:
- case CPP_STRING16:
- case CPP_STRING32:
- case CPP_UTF8STRING:
- case CPP_WCHAR:
- case CPP_CHAR16:
- case CPP_CHAR32:
- case CPP_NAME:
- case CPP_STRING:
- case CPP_NUMBER:
- if (!macro->fun_like)
- supported = 0;
- else
- buffer = cpp_spell_token (parse_in, token, buffer, false);
- break;
- case CPP_CHAR:
- is_char = 1;
- {
- unsigned chars_seen;
- int ignored;
- cppchar_t c;
- c = cpp_interpret_charconst (parse_in, token,
- &chars_seen, &ignored);
- if (c >= 32 && c <= 126)
- {
- *buffer++ = '\'';
- *buffer++ = (char) c;
- *buffer++ = '\'';
- }
- else
- {
- chars_seen = sprintf
- ((char *) buffer, "Character'Val (%d)", (int) c);
- buffer += chars_seen;
- }
- }
- break;
- case CPP_LSHIFT:
- if (prev_is_one)
- {
- /* Replace "1 << N" by "2 ** N" */
- *char_one = '2';
- *buffer++ = '*';
- *buffer++ = '*';
- break;
- }
- /* fallthrough */
- case CPP_RSHIFT:
- case CPP_COMPL:
- case CPP_QUERY:
- case CPP_EOF:
- case CPP_PLUS_EQ:
- case CPP_MINUS_EQ:
- case CPP_MULT_EQ:
- case CPP_DIV_EQ:
- case CPP_MOD_EQ:
- case CPP_AND_EQ:
- case CPP_OR_EQ:
- case CPP_XOR_EQ:
- case CPP_RSHIFT_EQ:
- case CPP_LSHIFT_EQ:
- case CPP_PRAGMA:
- case CPP_PRAGMA_EOL:
- case CPP_HASH:
- case CPP_PASTE:
- case CPP_OPEN_BRACE:
- case CPP_CLOSE_BRACE:
- case CPP_SEMICOLON:
- case CPP_ELLIPSIS:
- case CPP_PLUS_PLUS:
- case CPP_MINUS_MINUS:
- case CPP_DEREF_STAR:
- case CPP_DOT_STAR:
- case CPP_ATSIGN:
- case CPP_HEADER_NAME:
- case CPP_AT_NAME:
- case CPP_OTHER:
- case CPP_OBJC_STRING:
- default:
- if (!macro->fun_like)
- supported = 0;
- else
- buffer = cpp_spell_token (parse_in, token, buffer, false);
- break;
- }
- prev_is_one = is_one;
- }
- if (supported)
- *buffer = '\0';
- }
- if (macro->fun_like && supported)
- {
- char *start = (char *) s;
- int is_function = 0;
- pp_string (pp, " -- arg-macro: ");
- if (*start == '(' && buffer[-1] == ')')
- {
- start++;
- buffer[-1] = '\0';
- is_function = 1;
- pp_string (pp, "function ");
- }
- else
- {
- pp_string (pp, "procedure ");
- }
- pp_string (pp, (const char *) NODE_NAME (node));
- pp_space (pp);
- pp_string (pp, (char *) params);
- pp_newline (pp);
- pp_string (pp, " -- ");
- if (is_function)
- {
- pp_string (pp, "return ");
- pp_string (pp, start);
- pp_semicolon (pp);
- }
- else
- pp_string (pp, start);
- pp_newline (pp);
- }
- else if (supported)
- {
- expanded_location sloc = expand_location (macro->line);
- if (sloc.line != prev_line + 1)
- pp_newline (pp);
- num_macros++;
- prev_line = sloc.line;
- pp_string (pp, " ");
- ada_name = to_ada_name ((const char *) NODE_NAME (node), NULL);
- pp_string (pp, ada_name);
- free (ada_name);
- pp_string (pp, " : ");
- if (is_string)
- pp_string (pp, "aliased constant String");
- else if (is_char)
- pp_string (pp, "aliased constant Character");
- else
- pp_string (pp, "constant");
- pp_string (pp, " := ");
- pp_string (pp, (char *) s);
- if (is_string)
- pp_string (pp, " & ASCII.NUL");
- pp_string (pp, "; -- ");
- pp_string (pp, sloc.file);
- pp_colon (pp);
- pp_scalar (pp, "%d", sloc.line);
- pp_newline (pp);
- }
- else
- {
- pp_string (pp, " -- unsupported macro: ");
- pp_string (pp, (const char *) cpp_macro_definition (parse_in, node));
- pp_newline (pp);
- }
- }
- if (num_macros > 0)
- pp_newline (pp);
- }
- static const char *source_file;
- static int max_ada_macros;
- /* Callback used to count the number of relevant macros from
- cpp_forall_identifiers. PFILE and V are not used. NODE is the current macro
- to consider. */
- static int
- count_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *node,
- void *v ATTRIBUTE_UNUSED)
- {
- const cpp_macro *macro = node->value.macro;
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
- && macro->count
- && *NODE_NAME (node) != '_'
- && LOCATION_FILE (macro->line) == source_file)
- max_ada_macros++;
- return 1;
- }
- static int store_ada_macro_index;
- /* Callback used to store relevant macros from cpp_forall_identifiers.
- PFILE is not used. NODE is the current macro to store if relevant.
- MACROS is an array of cpp_hashnode* used to store NODE. */
- static int
- store_ada_macro (cpp_reader *pfile ATTRIBUTE_UNUSED,
- cpp_hashnode *node, void *macros)
- {
- const cpp_macro *macro = node->value.macro;
- if (node->type == NT_MACRO && !(node->flags & NODE_BUILTIN)
- && macro->count
- && *NODE_NAME (node) != '_'
- && LOCATION_FILE (macro->line) == source_file)
- ((cpp_hashnode **) macros)[store_ada_macro_index++] = node;
- return 1;
- }
- /* Callback used to compare (during qsort) macros. NODE1 and NODE2 are the
- two macro nodes to compare. */
- static int
- compare_macro (const void *node1, const void *node2)
- {
- typedef const cpp_hashnode *const_hnode;
- const_hnode n1 = *(const const_hnode *) node1;
- const_hnode n2 = *(const const_hnode *) node2;
- return n1->value.macro->line - n2->value.macro->line;
- }
- /* Dump in PP all relevant macros appearing in FILE. */
- static void
- dump_ada_macros (pretty_printer *pp, const char* file)
- {
- cpp_hashnode **macros;
- /* Initialize file-scope variables. */
- max_ada_macros = 0;
- store_ada_macro_index = 0;
- source_file = file;
- /* Count all potentially relevant macros, and then sort them by sloc. */
- cpp_forall_identifiers (parse_in, count_ada_macro, NULL);
- macros = XALLOCAVEC (cpp_hashnode *, max_ada_macros);
- cpp_forall_identifiers (parse_in, store_ada_macro, macros);
- qsort (macros, max_ada_macros, sizeof (cpp_hashnode *), compare_macro);
- print_ada_macros (pp, macros, max_ada_macros);
- }
- /* Current source file being handled. */
- static const char *source_file_base;
- /* Compare the declaration (DECL) of struct-like types based on the sloc of
- their last field (if LAST is true), so that more nested types collate before
- less nested ones.
- If ORIG_TYPE is true, also consider struct with a DECL_ORIGINAL_TYPE. */
- static location_t
- decl_sloc_common (const_tree decl, bool last, bool orig_type)
- {
- tree type = TREE_TYPE (decl);
- if (TREE_CODE (decl) == TYPE_DECL
- && (orig_type || !DECL_ORIGINAL_TYPE (decl))
- && RECORD_OR_UNION_TYPE_P (type)
- && TYPE_FIELDS (type))
- {
- tree f = TYPE_FIELDS (type);
- if (last)
- while (TREE_CHAIN (f))
- f = TREE_CHAIN (f);
- return DECL_SOURCE_LOCATION (f);
- }
- else
- return DECL_SOURCE_LOCATION (decl);
- }
- /* Return sloc of DECL, using sloc of last field if LAST is true. */
- location_t
- decl_sloc (const_tree decl, bool last)
- {
- return decl_sloc_common (decl, last, false);
- }
- /* Compare two locations LHS and RHS. */
- static int
- compare_location (location_t lhs, location_t rhs)
- {
- expanded_location xlhs = expand_location (lhs);
- expanded_location xrhs = expand_location (rhs);
- if (xlhs.file != xrhs.file)
- return filename_cmp (xlhs.file, xrhs.file);
- if (xlhs.line != xrhs.line)
- return xlhs.line - xrhs.line;
- if (xlhs.column != xrhs.column)
- return xlhs.column - xrhs.column;
- return 0;
- }
- /* Compare two declarations (LP and RP) by their source location. */
- static int
- compare_node (const void *lp, const void *rp)
- {
- const_tree lhs = *((const tree *) lp);
- const_tree rhs = *((const tree *) rp);
- return compare_location (decl_sloc (lhs, true), decl_sloc (rhs, true));
- }
- /* Compare two comments (LP and RP) by their source location. */
- static int
- compare_comment (const void *lp, const void *rp)
- {
- const cpp_comment *lhs = (const cpp_comment *) lp;
- const cpp_comment *rhs = (const cpp_comment *) rp;
- return compare_location (lhs->sloc, rhs->sloc);
- }
- static tree *to_dump = NULL;
- static int to_dump_count = 0;
- /* Collect a list of declarations from T relevant to SOURCE_FILE to be dumped
- by a subsequent call to dump_ada_nodes. */
- void
- collect_ada_nodes (tree t, const char *source_file)
- {
- tree n;
- int i = to_dump_count;
- /* Count the likely relevant nodes. */
- for (n = t; n; n = TREE_CHAIN (n))
- if (!DECL_IS_BUILTIN (n)
- && LOCATION_FILE (decl_sloc (n, false)) == source_file)
- to_dump_count++;
- /* Allocate sufficient storage for all nodes. */
- to_dump = XRESIZEVEC (tree, to_dump, to_dump_count);
- /* Store the relevant nodes. */
- for (n = t; n; n = TREE_CHAIN (n))
- if (!DECL_IS_BUILTIN (n)
- && LOCATION_FILE (decl_sloc (n, false)) == source_file)
- to_dump[i++] = n;
- }
- /* Call back for walk_tree to clear the TREE_VISITED flag of TP. */
- static tree
- unmark_visited_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
- {
- if (TREE_VISITED (*tp))
- TREE_VISITED (*tp) = 0;
- else
- *walk_subtrees = 0;
- return NULL_TREE;
- }
- /* Dump nodes into PP relevant to SOURCE_FILE, as collected by previous calls
- to collect_ada_nodes. */
- static void
- dump_ada_nodes (pretty_printer *pp, const char *source_file)
- {
- int i, j;
- cpp_comment_table *comments;
- /* Sort the table of declarations to dump by sloc. */
- qsort (to_dump, to_dump_count, sizeof (tree), compare_node);
- /* Fetch the table of comments. */
- comments = cpp_get_comments (parse_in);
- /* Sort the comments table by sloc. */
- if (comments->count > 1)
- qsort (comments->entries, comments->count, sizeof (cpp_comment),
- compare_comment);
- /* Interleave comments and declarations in line number order. */
- i = j = 0;
- do
- {
- /* Advance j until comment j is in this file. */
- while (j != comments->count
- && LOCATION_FILE (comments->entries[j].sloc) != source_file)
- j++;
- /* Advance j until comment j is not a duplicate. */
- while (j < comments->count - 1
- && !compare_comment (&comments->entries[j],
- &comments->entries[j + 1]))
- j++;
- /* Write decls until decl i collates after comment j. */
- while (i != to_dump_count)
- {
- if (j == comments->count
- || LOCATION_LINE (decl_sloc (to_dump[i], false))
- < LOCATION_LINE (comments->entries[j].sloc))
- print_generic_ada_decl (pp, to_dump[i++], source_file);
- else
- break;
- }
- /* Write comment j, if there is one. */
- if (j != comments->count)
- print_comment (pp, comments->entries[j++].comment);
- } while (i != to_dump_count || j != comments->count);
- /* Clear the TREE_VISITED flag over each subtree we've dumped. */
- for (i = 0; i < to_dump_count; i++)
- walk_tree (&to_dump[i], unmark_visited_r, NULL, NULL);
- /* Finalize the to_dump table. */
- if (to_dump)
- {
- free (to_dump);
- to_dump = NULL;
- to_dump_count = 0;
- }
- }
- /* Print a COMMENT to the output stream PP. */
- static void
- print_comment (pretty_printer *pp, const char *comment)
- {
- int len = strlen (comment);
- char *str = XALLOCAVEC (char, len + 1);
- char *tok;
- bool extra_newline = false;
- memcpy (str, comment, len + 1);
- /* Trim C/C++ comment indicators. */
- if (str[len - 2] == '*' && str[len - 1] == '/')
- {
- str[len - 2] = ' ';
- str[len - 1] = '\0';
- }
- str += 2;
- tok = strtok (str, "\n");
- while (tok) {
- pp_string (pp, " --");
- pp_string (pp, tok);
- pp_newline (pp);
- tok = strtok (NULL, "\n");
- /* Leave a blank line after multi-line comments. */
- if (tok)
- extra_newline = true;
- }
- if (extra_newline)
- pp_newline (pp);
- }
- /* Print declaration DECL to PP in Ada syntax. The current source file being
- handled is SOURCE_FILE. */
- static void
- print_generic_ada_decl (pretty_printer *pp, tree decl, const char *source_file)
- {
- source_file_base = source_file;
- if (print_ada_declaration (pp, decl, 0, INDENT_INCR))
- {
- pp_newline (pp);
- pp_newline (pp);
- }
- }
- /* Dump a newline and indent BUFFER by SPC chars. */
- static void
- newline_and_indent (pretty_printer *buffer, int spc)
- {
- pp_newline (buffer);
- INDENT (spc);
- }
- struct with { char *s; const char *in_file; int limited; };
- static struct with *withs = NULL;
- static int withs_max = 4096;
- static int with_len = 0;
- /* Record a "with" clause on package S (a limited with if LIMITED_ACCESS is
- true), if not already done. */
- static void
- append_withs (const char *s, int limited_access)
- {
- int i;
- if (withs == NULL)
- withs = XNEWVEC (struct with, withs_max);
- if (with_len == withs_max)
- {
- withs_max *= 2;
- withs = XRESIZEVEC (struct with, withs, withs_max);
- }
- for (i = 0; i < with_len; i++)
- if (!strcmp (s, withs[i].s)
- && source_file_base == withs[i].in_file)
- {
- withs[i].limited &= limited_access;
- return;
- }
- withs[with_len].s = xstrdup (s);
- withs[with_len].in_file = source_file_base;
- withs[with_len].limited = limited_access;
- with_len++;
- }
- /* Reset "with" clauses. */
- static void
- reset_ada_withs (void)
- {
- int i;
- if (!withs)
- return;
- for (i = 0; i < with_len; i++)
- free (withs[i].s);
- free (withs);
- withs = NULL;
- withs_max = 4096;
- with_len = 0;
- }
- /* Dump "with" clauses in F. */
- static void
- dump_ada_withs (FILE *f)
- {
- int i;
- fprintf (f, "with Interfaces.C; use Interfaces.C;\n");
- for (i = 0; i < with_len; i++)
- fprintf
- (f, "%swith %s;\n", withs[i].limited ? "limited " : "", withs[i].s);
- }
- /* Return suitable Ada package name from FILE. */
- static char *
- get_ada_package (const char *file)
- {
- const char *base;
- char *res;
- const char *s;
- int i;
- size_t plen;
- s = strstr (file, "/include/");
- if (s)
- base = s + 9;
- else
- base = lbasename (file);
- if (ada_specs_parent == NULL)
- plen = 0;
- else
- plen = strlen (ada_specs_parent) + 1;
- res = XNEWVEC (char, plen + strlen (base) + 1);
- if (ada_specs_parent != NULL) {
- strcpy (res, ada_specs_parent);
- res[plen - 1] = '.';
- }
- for (i = plen; *base; base++, i++)
- switch (*base)
- {
- case '+':
- res[i] = 'p';
- break;
- case '.':
- case '-':
- case '_':
- case '/':
- case '\\':
- res[i] = (i == 0 || res[i - 1] == '.' || res[i - 1] == '_') ? 'u' : '_';
- break;
- default:
- res[i] = *base;
- break;
- }
- res[i] = '\0';
- return res;
- }
- static const char *ada_reserved[] = {
- "abort", "abs", "abstract", "accept", "access", "aliased", "all", "and",
- "array", "at", "begin", "body", "case", "constant", "declare", "delay",
- "delta", "digits", "do", "else", "elsif", "end", "entry", "exception",
- "exit", "for", "function", "generic", "goto", "if", "in", "interface", "is",
- "limited", "loop", "mod", "new", "not", "null", "others", "out", "of", "or",
- "overriding", "package", "pragma", "private", "procedure", "protected",
- "raise", "range", "record", "rem", "renames", "requeue", "return", "reverse",
- "select", "separate", "subtype", "synchronized", "tagged", "task",
- "terminate", "then", "type", "until", "use", "when", "while", "with", "xor",
- NULL};
- /* ??? would be nice to specify this list via a config file, so that users
- can create their own dictionary of conflicts. */
- static const char *c_duplicates[] = {
- /* system will cause troubles with System.Address. */
- "system",
- /* The following values have other definitions with same name/other
- casing. */
- "funmap",
- "rl_vi_fWord",
- "rl_vi_bWord",
- "rl_vi_eWord",
- "rl_readline_version",
- "_Vx_ushort",
- "USHORT",
- "XLookupKeysym",
- NULL};
- /* Return a declaration tree corresponding to TYPE. */
- static tree
- get_underlying_decl (tree type)
- {
- tree decl = NULL_TREE;
- if (type == NULL_TREE)
- return NULL_TREE;
- /* type is a declaration. */
- if (DECL_P (type))
- decl = type;
- /* type is a typedef. */
- if (TYPE_P (type) && TYPE_NAME (type) && DECL_P (TYPE_NAME (type)))
- decl = TYPE_NAME (type);
- /* TYPE_STUB_DECL has been set for type. */
- if (TYPE_P (type) && TYPE_STUB_DECL (type) &&
- DECL_P (TYPE_STUB_DECL (type)))
- decl = TYPE_STUB_DECL (type);
- return decl;
- }
- /* Return whether TYPE has static fields. */
- static bool
- has_static_fields (const_tree type)
- {
- tree tmp;
- if (!type || !RECORD_OR_UNION_TYPE_P (type))
- return false;
- for (tmp = TYPE_FIELDS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (DECL_NAME (tmp) && TREE_STATIC (tmp))
- return true;
- return false;
- }
- /* Return whether TYPE corresponds to an Ada tagged type (has a dispatch
- table). */
- static bool
- is_tagged_type (const_tree type)
- {
- tree tmp;
- if (!type || !RECORD_OR_UNION_TYPE_P (type))
- return false;
- for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (TREE_CODE (tmp) == FUNCTION_DECL && DECL_VINDEX (tmp))
- return true;
- return false;
- }
- /* Return whether TYPE has non-trivial methods, i.e. methods that do something
- for the objects of TYPE. In C++, all classes have implicit special methods,
- e.g. constructors and destructors, but they can be trivial if the type is
- sufficiently simple. */
- static bool
- has_nontrivial_methods (tree type)
- {
- tree tmp;
- if (!type || !RECORD_OR_UNION_TYPE_P (type))
- return false;
- /* Only C++ types can have methods. */
- if (!cpp_check)
- return false;
- /* A non-trivial type has non-trivial special methods. */
- if (!cpp_check (type, IS_TRIVIAL))
- return true;
- /* If there are user-defined methods, they are deemed non-trivial. */
- for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (!DECL_ARTIFICIAL (tmp))
- return true;
- return false;
- }
- /* Generate a legal Ada name from a C NAME, returning a malloc'd string.
- SPACE_FOUND, if not NULL, is used to indicate whether a space was found in
- NAME. */
- static char *
- to_ada_name (const char *name, int *space_found)
- {
- const char **names;
- int len = strlen (name);
- int j, len2 = 0;
- int found = false;
- char *s = XNEWVEC (char, len * 2 + 5);
- char c;
- if (space_found)
- *space_found = false;
- /* Add trailing "c_" if name is an Ada reserved word. */
- for (names = ada_reserved; *names; names++)
- if (!strcasecmp (name, *names))
- {
- s[len2++] = 'c';
- s[len2++] = '_';
- found = true;
- break;
- }
- if (!found)
- /* Add trailing "c_" if name is an potential case sensitive duplicate. */
- for (names = c_duplicates; *names; names++)
- if (!strcmp (name, *names))
- {
- s[len2++] = 'c';
- s[len2++] = '_';
- found = true;
- break;
- }
- for (j = 0; name[j] == '_'; j++)
- s[len2++] = 'u';
- if (j > 0)
- s[len2++] = '_';
- else if (*name == '.' || *name == '$')
- {
- s[0] = 'a';
- s[1] = 'n';
- s[2] = 'o';
- s[3] = 'n';
- len2 = 4;
- j++;
- }
- /* Replace unsuitable characters for Ada identifiers. */
- for (; j < len; j++)
- switch (name[j])
- {
- case ' ':
- if (space_found)
- *space_found = true;
- s[len2++] = '_';
- break;
- /* ??? missing some C++ operators. */
- case '=':
- s[len2++] = '_';
- if (name[j + 1] == '=')
- {
- j++;
- s[len2++] = 'e';
- s[len2++] = 'q';
- }
- else
- {
- s[len2++] = 'a';
- s[len2++] = 's';
- }
- break;
- case '!':
- s[len2++] = '_';
- if (name[j + 1] == '=')
- {
- j++;
- s[len2++] = 'n';
- s[len2++] = 'e';
- }
- break;
- case '~':
- s[len2++] = '_';
- s[len2++] = 't';
- s[len2++] = 'i';
- break;
- case '&':
- case '|':
- case '^':
- s[len2++] = '_';
- s[len2++] = name[j] == '&' ? 'a' : name[j] == '|' ? 'o' : 'x';
- if (name[j + 1] == '=')
- {
- j++;
- s[len2++] = 'e';
- }
- break;
- case '+':
- case '-':
- case '*':
- case '/':
- case '(':
- case '[':
- if (s[len2 - 1] != '_')
- s[len2++] = '_';
- switch (name[j + 1]) {
- case '\0':
- j++;
- switch (name[j - 1]) {
- case '+': s[len2++] = 'p'; break; /* + */
- case '-': s[len2++] = 'm'; break; /* - */
- case '*': s[len2++] = 't'; break; /* * */
- case '/': s[len2++] = 'd'; break; /* / */
- }
- break;
- case '=':
- j++;
- switch (name[j - 1]) {
- case '+': s[len2++] = 'p'; break; /* += */
- case '-': s[len2++] = 'm'; break; /* -= */
- case '*': s[len2++] = 't'; break; /* *= */
- case '/': s[len2++] = 'd'; break; /* /= */
- }
- s[len2++] = 'a';
- break;
- case '-': /* -- */
- j++;
- s[len2++] = 'm';
- s[len2++] = 'm';
- break;
- case '+': /* ++ */
- j++;
- s[len2++] = 'p';
- s[len2++] = 'p';
- break;
- case ')': /* () */
- j++;
- s[len2++] = 'o';
- s[len2++] = 'p';
- break;
- case ']': /* [] */
- j++;
- s[len2++] = 'o';
- s[len2++] = 'b';
- break;
- }
- break;
- case '<':
- case '>':
- c = name[j] == '<' ? 'l' : 'g';
- s[len2++] = '_';
- switch (name[j + 1]) {
- case '\0':
- s[len2++] = c;
- s[len2++] = 't';
- break;
- case '=':
- j++;
- s[len2++] = c;
- s[len2++] = 'e';
- break;
- case '>':
- j++;
- s[len2++] = 's';
- s[len2++] = 'r';
- break;
- case '<':
- j++;
- s[len2++] = 's';
- s[len2++] = 'l';
- break;
- default:
- break;
- }
- break;
- case '_':
- if (len2 && s[len2 - 1] == '_')
- s[len2++] = 'u';
- /* fall through */
- default:
- s[len2++] = name[j];
- }
- if (s[len2 - 1] == '_')
- s[len2++] = 'u';
- s[len2] = '\0';
- return s;
- }
- /* Return true if DECL refers to a C++ class type for which a
- separate enclosing package has been or should be generated. */
- static bool
- separate_class_package (tree decl)
- {
- tree type = TREE_TYPE (decl);
- return has_nontrivial_methods (type) || has_static_fields (type);
- }
- static bool package_prefix = true;
- /* Dump in BUFFER the name of an identifier NODE of type TYPE, following Ada
- syntax. LIMITED_ACCESS indicates whether NODE can be accessed via a limited
- 'with' clause rather than a regular 'with' clause. */
- static void
- pp_ada_tree_identifier (pretty_printer *buffer, tree node, tree type,
- int limited_access)
- {
- const char *name = IDENTIFIER_POINTER (node);
- int space_found = false;
- char *s = to_ada_name (name, &space_found);
- tree decl;
- /* If the entity is a type and comes from another file, generate "package"
- prefix. */
- decl = get_underlying_decl (type);
- if (decl)
- {
- expanded_location xloc = expand_location (decl_sloc (decl, false));
- if (xloc.file && xloc.line)
- {
- if (xloc.file != source_file_base)
- {
- switch (TREE_CODE (type))
- {
- case ENUMERAL_TYPE:
- case INTEGER_TYPE:
- case REAL_TYPE:
- case FIXED_POINT_TYPE:
- case BOOLEAN_TYPE:
- case REFERENCE_TYPE:
- case POINTER_TYPE:
- case ARRAY_TYPE:
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- case TYPE_DECL:
- if (package_prefix)
- {
- char *s1 = get_ada_package (xloc.file);
- append_withs (s1, limited_access);
- pp_string (buffer, s1);
- pp_dot (buffer);
- free (s1);
- }
- break;
- default:
- break;
- }
- /* Generate the additional package prefix for C++ classes. */
- if (separate_class_package (decl))
- {
- pp_string (buffer, "Class_");
- pp_string (buffer, s);
- pp_dot (buffer);
- }
- }
- }
- }
- if (space_found)
- if (!strcmp (s, "short_int"))
- pp_string (buffer, "short");
- else if (!strcmp (s, "short_unsigned_int"))
- pp_string (buffer, "unsigned_short");
- else if (!strcmp (s, "unsigned_int"))
- pp_string (buffer, "unsigned");
- else if (!strcmp (s, "long_int"))
- pp_string (buffer, "long");
- else if (!strcmp (s, "long_unsigned_int"))
- pp_string (buffer, "unsigned_long");
- else if (!strcmp (s, "long_long_int"))
- pp_string (buffer, "Long_Long_Integer");
- else if (!strcmp (s, "long_long_unsigned_int"))
- {
- if (package_prefix)
- {
- append_withs ("Interfaces.C.Extensions", false);
- pp_string (buffer, "Extensions.unsigned_long_long");
- }
- else
- pp_string (buffer, "unsigned_long_long");
- }
- else
- pp_string(buffer, s);
- else
- if (!strcmp (s, "bool"))
- {
- if (package_prefix)
- {
- append_withs ("Interfaces.C.Extensions", false);
- pp_string (buffer, "Extensions.bool");
- }
- else
- pp_string (buffer, "bool");
- }
- else
- pp_string(buffer, s);
- free (s);
- }
- /* Dump in BUFFER the assembly name of T. */
- static void
- pp_asm_name (pretty_printer *buffer, tree t)
- {
- tree name = DECL_ASSEMBLER_NAME (t);
- char *ada_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (name) + 1), *s;
- const char *ident = IDENTIFIER_POINTER (name);
- for (s = ada_name; *ident; ident++)
- {
- if (*ident == ' ')
- break;
- else if (*ident != '*')
- *s++ = *ident;
- }
- *s = '\0';
- pp_string (buffer, ada_name);
- }
- /* Dump in BUFFER the name of a DECL node if set, following Ada syntax.
- LIMITED_ACCESS indicates whether NODE can be accessed via a limited
- 'with' clause rather than a regular 'with' clause. */
- static void
- dump_ada_decl_name (pretty_printer *buffer, tree decl, int limited_access)
- {
- if (DECL_NAME (decl))
- pp_ada_tree_identifier (buffer, DECL_NAME (decl), decl, limited_access);
- else
- {
- tree type_name = TYPE_NAME (TREE_TYPE (decl));
- if (!type_name)
- {
- pp_string (buffer, "anon");
- if (TREE_CODE (decl) == FIELD_DECL)
- pp_scalar (buffer, "%d", DECL_UID (decl));
- else
- pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (decl)));
- }
- else if (TREE_CODE (type_name) == IDENTIFIER_NODE)
- pp_ada_tree_identifier (buffer, type_name, decl, limited_access);
- }
- }
- /* Dump in BUFFER a name based on both T1 and T2, followed by S. */
- static void
- dump_ada_double_name (pretty_printer *buffer, tree t1, tree t2, const char *s)
- {
- if (DECL_NAME (t1))
- pp_ada_tree_identifier (buffer, DECL_NAME (t1), t1, false);
- else
- {
- pp_string (buffer, "anon");
- pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t1)));
- }
- pp_underscore (buffer);
- if (DECL_NAME (t2))
- pp_ada_tree_identifier (buffer, DECL_NAME (t2), t2, false);
- else
- {
- pp_string (buffer, "anon");
- pp_scalar (buffer, "%d", TYPE_UID (TREE_TYPE (t2)));
- }
- pp_string (buffer, s);
- }
- /* Dump in BUFFER pragma Import C/CPP on a given node T. */
- static void
- dump_ada_import (pretty_printer *buffer, tree t)
- {
- const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t));
- int is_stdcall = TREE_CODE (t) == FUNCTION_DECL &&
- lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (t)));
- if (is_stdcall)
- pp_string (buffer, "pragma Import (Stdcall, ");
- else if (name[0] == '_' && name[1] == 'Z')
- pp_string (buffer, "pragma Import (CPP, ");
- else
- pp_string (buffer, "pragma Import (C, ");
- dump_ada_decl_name (buffer, t, false);
- pp_string (buffer, ", \"");
- if (is_stdcall)
- pp_string (buffer, IDENTIFIER_POINTER (DECL_NAME (t)));
- else
- pp_asm_name (buffer, t);
- pp_string (buffer, "\");");
- }
- /* Check whether T and its type have different names, and append "the_"
- otherwise in BUFFER. */
- static void
- check_name (pretty_printer *buffer, tree t)
- {
- const char *s;
- tree tmp = TREE_TYPE (t);
- while (TREE_CODE (tmp) == POINTER_TYPE && !TYPE_NAME (tmp))
- tmp = TREE_TYPE (tmp);
- if (TREE_CODE (tmp) != FUNCTION_TYPE)
- {
- if (TREE_CODE (tmp) == IDENTIFIER_NODE)
- s = IDENTIFIER_POINTER (tmp);
- else if (!TYPE_NAME (tmp))
- s = "";
- else if (TREE_CODE (TYPE_NAME (tmp)) == IDENTIFIER_NODE)
- s = IDENTIFIER_POINTER (TYPE_NAME (tmp));
- else
- s = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp)));
- if (!strcasecmp (IDENTIFIER_POINTER (DECL_NAME (t)), s))
- pp_string (buffer, "the_");
- }
- }
- /* Dump in BUFFER a function declaration FUNC with Ada syntax.
- IS_METHOD indicates whether FUNC is a C++ method.
- IS_CONSTRUCTOR whether FUNC is a C++ constructor.
- IS_DESTRUCTOR whether FUNC is a C++ destructor.
- SPC is the current indentation level. */
- static int
- dump_ada_function_declaration (pretty_printer *buffer, tree func,
- int is_method, int is_constructor,
- int is_destructor, int spc)
- {
- tree arg;
- const tree node = TREE_TYPE (func);
- char buf[16];
- int num = 0, num_args = 0, have_args = true, have_ellipsis = false;
- /* Compute number of arguments. */
- arg = TYPE_ARG_TYPES (node);
- if (arg)
- {
- while (TREE_CHAIN (arg) && arg != error_mark_node)
- {
- num_args++;
- arg = TREE_CHAIN (arg);
- }
- if (TREE_CODE (TREE_VALUE (arg)) != VOID_TYPE)
- {
- num_args++;
- have_ellipsis = true;
- }
- }
- if (is_constructor)
- num_args--;
- if (is_destructor)
- num_args = 1;
- if (num_args > 2)
- newline_and_indent (buffer, spc + 1);
- if (num_args > 0)
- {
- pp_space (buffer);
- pp_left_paren (buffer);
- }
- if (TREE_CODE (func) == FUNCTION_DECL)
- arg = DECL_ARGUMENTS (func);
- else
- arg = NULL_TREE;
- if (arg == NULL_TREE)
- {
- have_args = false;
- arg = TYPE_ARG_TYPES (node);
- if (arg && TREE_CODE (TREE_VALUE (arg)) == VOID_TYPE)
- arg = NULL_TREE;
- }
- if (is_constructor)
- arg = TREE_CHAIN (arg);
- /* Print the argument names (if available) & types. */
- for (num = 1; num <= num_args; num++)
- {
- if (have_args)
- {
- if (DECL_NAME (arg))
- {
- check_name (buffer, arg);
- pp_ada_tree_identifier (buffer, DECL_NAME (arg), 0, false);
- pp_string (buffer, " : ");
- }
- else
- {
- sprintf (buf, "arg%d : ", num);
- pp_string (buffer, buf);
- }
- dump_generic_ada_node (buffer, TREE_TYPE (arg), node, spc, 0, true);
- }
- else
- {
- sprintf (buf, "arg%d : ", num);
- pp_string (buffer, buf);
- dump_generic_ada_node (buffer, TREE_VALUE (arg), node, spc, 0, true);
- }
- if (TREE_TYPE (arg) && TREE_TYPE (TREE_TYPE (arg))
- && is_tagged_type (TREE_TYPE (TREE_TYPE (arg))))
- {
- if (!is_method
- || (num != 1 || (!DECL_VINDEX (func) && !is_constructor)))
- pp_string (buffer, "'Class");
- }
- arg = TREE_CHAIN (arg);
- if (num < num_args)
- {
- pp_semicolon (buffer);
- if (num_args > 2)
- newline_and_indent (buffer, spc + INDENT_INCR);
- else
- pp_space (buffer);
- }
- }
- if (have_ellipsis)
- {
- pp_string (buffer, " -- , ...");
- newline_and_indent (buffer, spc + INDENT_INCR);
- }
- if (num_args > 0)
- pp_right_paren (buffer);
- return num_args;
- }
- /* Dump in BUFFER all the domains associated with an array NODE,
- using Ada syntax. SPC is the current indentation level. */
- static void
- dump_ada_array_domains (pretty_printer *buffer, tree node, int spc)
- {
- int first = 1;
- pp_left_paren (buffer);
- for (; TREE_CODE (node) == ARRAY_TYPE; node = TREE_TYPE (node))
- {
- tree domain = TYPE_DOMAIN (node);
- if (domain)
- {
- tree min = TYPE_MIN_VALUE (domain);
- tree max = TYPE_MAX_VALUE (domain);
- if (!first)
- pp_string (buffer, ", ");
- first = 0;
- if (min)
- dump_generic_ada_node (buffer, min, NULL_TREE, spc, 0, true);
- pp_string (buffer, " .. ");
- /* If the upper bound is zero, gcc may generate a NULL_TREE
- for TYPE_MAX_VALUE rather than an integer_cst. */
- if (max)
- dump_generic_ada_node (buffer, max, NULL_TREE, spc, 0, true);
- else
- pp_string (buffer, "0");
- }
- else
- pp_string (buffer, "size_t");
- }
- pp_right_paren (buffer);
- }
- /* Dump in BUFFER file:line information related to NODE. */
- static void
- dump_sloc (pretty_printer *buffer, tree node)
- {
- expanded_location xloc;
- xloc.file = NULL;
- if (TREE_CODE_CLASS (TREE_CODE (node)) == tcc_declaration)
- xloc = expand_location (DECL_SOURCE_LOCATION (node));
- else if (EXPR_HAS_LOCATION (node))
- xloc = expand_location (EXPR_LOCATION (node));
- if (xloc.file)
- {
- pp_string (buffer, xloc.file);
- pp_colon (buffer);
- pp_decimal_int (buffer, xloc.line);
- }
- }
- /* Return true if T designates a one dimension array of "char". */
- static bool
- is_char_array (tree t)
- {
- tree tmp;
- int num_dim = 0;
- /* Retrieve array's type. */
- tmp = t;
- while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
- {
- num_dim++;
- tmp = TREE_TYPE (tmp);
- }
- tmp = TREE_TYPE (tmp);
- return num_dim == 1 && TREE_CODE (tmp) == INTEGER_TYPE
- && !strcmp (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (tmp))), "char");
- }
- /* Dump in BUFFER an array type T in Ada syntax. Assume that the "type"
- keyword and name have already been printed. SPC is the indentation
- level. */
- static void
- dump_ada_array_type (pretty_printer *buffer, tree t, int spc)
- {
- tree tmp;
- bool char_array = is_char_array (t);
- /* Special case char arrays. */
- if (char_array)
- {
- pp_string (buffer, "Interfaces.C.char_array ");
- }
- else
- pp_string (buffer, "array ");
- /* Print the dimensions. */
- dump_ada_array_domains (buffer, TREE_TYPE (t), spc);
- /* Retrieve array's type. */
- tmp = TREE_TYPE (t);
- while (TREE_CODE (TREE_TYPE (tmp)) == ARRAY_TYPE)
- tmp = TREE_TYPE (tmp);
- /* Print array's type. */
- if (!char_array)
- {
- pp_string (buffer, " of ");
- if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE)
- pp_string (buffer, "aliased ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (tmp), TREE_TYPE (t), spc, false, true);
- }
- }
- /* Dump in BUFFER type names associated with a template, each prepended with
- '_'. TYPES is the TREE_PURPOSE of a DECL_TEMPLATE_INSTANTIATIONS. SPC is
- the indentation level. */
- static void
- dump_template_types (pretty_printer *buffer, tree types, int spc)
- {
- size_t i;
- size_t len = TREE_VEC_LENGTH (types);
- for (i = 0; i < len; i++)
- {
- tree elem = TREE_VEC_ELT (types, i);
- pp_underscore (buffer);
- if (!dump_generic_ada_node (buffer, elem, 0, spc, false, true))
- {
- pp_string (buffer, "unknown");
- pp_scalar (buffer, "%lu", (unsigned long) TREE_HASH (elem));
- }
- }
- }
- /* Dump in BUFFER the contents of all class instantiations associated with
- a given template T. SPC is the indentation level. */
- static int
- dump_ada_template (pretty_printer *buffer, tree t, int spc)
- {
- /* DECL_SIZE_UNIT is DECL_TEMPLATE_INSTANTIATIONS in this context. */
- tree inst = DECL_SIZE_UNIT (t);
- /* This emulates DECL_TEMPLATE_RESULT in this context. */
- struct tree_template_decl {
- struct tree_decl_common common;
- tree arguments;
- tree result;
- };
- tree result = ((struct tree_template_decl *) t)->result;
- int num_inst = 0;
- /* Don't look at template declarations declaring something coming from
- another file. This can occur for template friend declarations. */
- if (LOCATION_FILE (decl_sloc (result, false))
- != LOCATION_FILE (decl_sloc (t, false)))
- return 0;
- while (inst && inst != error_mark_node)
- {
- tree types = TREE_PURPOSE (inst);
- tree instance = TREE_VALUE (inst);
- if (TREE_VEC_LENGTH (types) == 0)
- break;
- if (!RECORD_OR_UNION_TYPE_P (instance) || !TYPE_METHODS (instance))
- break;
- num_inst++;
- INDENT (spc);
- pp_string (buffer, "package ");
- package_prefix = false;
- dump_generic_ada_node (buffer, instance, t, spc, false, true);
- dump_template_types (buffer, types, spc);
- pp_string (buffer, " is");
- spc += INDENT_INCR;
- newline_and_indent (buffer, spc);
- TREE_VISITED (get_underlying_decl (instance)) = 1;
- pp_string (buffer, "type ");
- dump_generic_ada_node (buffer, instance, t, spc, false, true);
- package_prefix = true;
- if (is_tagged_type (instance))
- pp_string (buffer, " is tagged limited ");
- else
- pp_string (buffer, " is limited ");
- dump_generic_ada_node (buffer, instance, t, spc, false, false);
- pp_newline (buffer);
- spc -= INDENT_INCR;
- newline_and_indent (buffer, spc);
- pp_string (buffer, "end;");
- newline_and_indent (buffer, spc);
- pp_string (buffer, "use ");
- package_prefix = false;
- dump_generic_ada_node (buffer, instance, t, spc, false, true);
- dump_template_types (buffer, types, spc);
- package_prefix = true;
- pp_semicolon (buffer);
- pp_newline (buffer);
- pp_newline (buffer);
- inst = TREE_CHAIN (inst);
- }
- return num_inst > 0;
- }
- /* Return true if NODE is a simple enum types, that can be mapped to an
- Ada enum type directly. */
- static bool
- is_simple_enum (tree node)
- {
- HOST_WIDE_INT count = 0;
- tree value;
- for (value = TYPE_VALUES (node); value; value = TREE_CHAIN (value))
- {
- tree int_val = TREE_VALUE (value);
- if (TREE_CODE (int_val) != INTEGER_CST)
- int_val = DECL_INITIAL (int_val);
- if (!tree_fits_shwi_p (int_val))
- return false;
- else if (tree_to_shwi (int_val) != count)
- return false;
- count++;
- }
- return true;
- }
- static bool bitfield_used = false;
- /* Recursively dump in BUFFER Ada declarations corresponding to NODE of type
- TYPE. SPC is the indentation level. LIMITED_ACCESS indicates whether NODE
- can be referenced via a "limited with" clause. NAME_ONLY indicates whether
- we should only dump the name of NODE, instead of its full declaration. */
- static int
- dump_generic_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
- int limited_access, bool name_only)
- {
- if (node == NULL_TREE)
- return 0;
- switch (TREE_CODE (node))
- {
- case ERROR_MARK:
- pp_string (buffer, "<<< error >>>");
- return 0;
- case IDENTIFIER_NODE:
- pp_ada_tree_identifier (buffer, node, type, limited_access);
- break;
- case TREE_LIST:
- pp_string (buffer, "--- unexpected node: TREE_LIST");
- return 0;
- case TREE_BINFO:
- dump_generic_ada_node
- (buffer, BINFO_TYPE (node), type, spc, limited_access, name_only);
- case TREE_VEC:
- pp_string (buffer, "--- unexpected node: TREE_VEC");
- return 0;
- case VOID_TYPE:
- if (package_prefix)
- {
- append_withs ("System", false);
- pp_string (buffer, "System.Address");
- }
- else
- pp_string (buffer, "address");
- break;
- case VECTOR_TYPE:
- pp_string (buffer, "<vector>");
- break;
- case COMPLEX_TYPE:
- pp_string (buffer, "<complex>");
- break;
- case ENUMERAL_TYPE:
- if (name_only)
- dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, spc, 0, true);
- else
- {
- tree value = TYPE_VALUES (node);
- if (is_simple_enum (node))
- {
- bool first = true;
- spc += INDENT_INCR;
- newline_and_indent (buffer, spc - 1);
- pp_left_paren (buffer);
- for (; value; value = TREE_CHAIN (value))
- {
- if (first)
- first = false;
- else
- {
- pp_comma (buffer);
- newline_and_indent (buffer, spc);
- }
- pp_ada_tree_identifier
- (buffer, TREE_PURPOSE (value), node, false);
- }
- pp_string (buffer, ");");
- spc -= INDENT_INCR;
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Convention (C, ");
- dump_generic_ada_node
- (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
- spc, 0, true);
- pp_right_paren (buffer);
- }
- else
- {
- pp_string (buffer, "unsigned");
- for (; value; value = TREE_CHAIN (value))
- {
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- pp_ada_tree_identifier
- (buffer, TREE_PURPOSE (value), node, false);
- pp_string (buffer, " : constant ");
- dump_generic_ada_node
- (buffer, DECL_NAME (type) ? type : TYPE_NAME (node), type,
- spc, 0, true);
- pp_string (buffer, " := ");
- dump_generic_ada_node
- (buffer,
- TREE_CODE (TREE_VALUE (value)) == INTEGER_CST ?
- TREE_VALUE (value) : DECL_INITIAL (TREE_VALUE (value)),
- node, spc, false, true);
- }
- }
- }
- break;
- case INTEGER_TYPE:
- case REAL_TYPE:
- case FIXED_POINT_TYPE:
- case BOOLEAN_TYPE:
- {
- enum tree_code_class tclass;
- tclass = TREE_CODE_CLASS (TREE_CODE (node));
- if (tclass == tcc_declaration)
- {
- if (DECL_NAME (node))
- pp_ada_tree_identifier
- (buffer, DECL_NAME (node), 0, limited_access);
- else
- pp_string (buffer, "<unnamed type decl>");
- }
- else if (tclass == tcc_type)
- {
- if (TYPE_NAME (node))
- {
- if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
- pp_ada_tree_identifier (buffer, TYPE_NAME (node),
- node, limited_access);
- else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
- && DECL_NAME (TYPE_NAME (node)))
- dump_ada_decl_name (buffer, TYPE_NAME (node), limited_access);
- else
- pp_string (buffer, "<unnamed type>");
- }
- else if (TREE_CODE (node) == INTEGER_TYPE)
- {
- append_withs ("Interfaces.C.Extensions", false);
- bitfield_used = true;
- if (TYPE_PRECISION (node) == 1)
- pp_string (buffer, "Extensions.Unsigned_1");
- else
- {
- pp_string (buffer, (TYPE_UNSIGNED (node)
- ? "Extensions.Unsigned_"
- : "Extensions.Signed_"));
- pp_decimal_int (buffer, TYPE_PRECISION (node));
- }
- }
- else
- pp_string (buffer, "<unnamed type>");
- }
- break;
- }
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- if (name_only && TYPE_NAME (node))
- dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, spc, limited_access, true);
- else if (TREE_CODE (TREE_TYPE (node)) == FUNCTION_TYPE)
- {
- tree fnode = TREE_TYPE (node);
- bool is_function;
- if (VOID_TYPE_P (TREE_TYPE (fnode)))
- {
- is_function = false;
- pp_string (buffer, "access procedure");
- }
- else
- {
- is_function = true;
- pp_string (buffer, "access function");
- }
- dump_ada_function_declaration
- (buffer, node, false, false, false, spc + INDENT_INCR);
- if (is_function)
- {
- pp_string (buffer, " return ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (fnode), type, spc, 0, true);
- }
- /* If we are dumping the full type, it means we are part of a
- type definition and need also a Convention C pragma. */
- if (!name_only)
- {
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Convention (C, ");
- dump_generic_ada_node
- (buffer, type, 0, spc, false, true);
- pp_right_paren (buffer);
- }
- }
- else
- {
- int is_access = false;
- unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
- if (VOID_TYPE_P (TREE_TYPE (node)))
- {
- if (!name_only)
- pp_string (buffer, "new ");
- if (package_prefix)
- {
- append_withs ("System", false);
- pp_string (buffer, "System.Address");
- }
- else
- pp_string (buffer, "address");
- }
- else
- {
- if (TREE_CODE (node) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
- && !strcmp
- (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME
- (TREE_TYPE (node)))), "char"))
- {
- if (!name_only)
- pp_string (buffer, "new ");
- if (package_prefix)
- {
- pp_string (buffer, "Interfaces.C.Strings.chars_ptr");
- append_withs ("Interfaces.C.Strings", false);
- }
- else
- pp_string (buffer, "chars_ptr");
- }
- else
- {
- /* For now, handle all access-to-access or
- access-to-unknown-structs as opaque system.address. */
- tree type_name = TYPE_NAME (TREE_TYPE (node));
- const_tree typ2 = !type ||
- DECL_P (type) ? type : TYPE_NAME (type);
- const_tree underlying_type =
- get_underlying_decl (TREE_TYPE (node));
- if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE
- /* Pointer to pointer. */
- || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
- && (!underlying_type
- || !TYPE_FIELDS (TREE_TYPE (underlying_type))))
- /* Pointer to opaque structure. */
- || underlying_type == NULL_TREE
- || (!typ2
- && !TREE_VISITED (underlying_type)
- && !TREE_VISITED (type_name)
- && !is_tagged_type (TREE_TYPE (node))
- && DECL_SOURCE_FILE (underlying_type)
- == source_file_base)
- || (type_name && typ2
- && DECL_P (underlying_type)
- && DECL_P (typ2)
- && decl_sloc (underlying_type, true)
- > decl_sloc (typ2, true)
- && DECL_SOURCE_FILE (underlying_type)
- == DECL_SOURCE_FILE (typ2)))
- {
- if (package_prefix)
- {
- append_withs ("System", false);
- if (!name_only)
- pp_string (buffer, "new ");
- pp_string (buffer, "System.Address");
- }
- else
- pp_string (buffer, "address");
- return spc;
- }
- if (!package_prefix)
- pp_string (buffer, "access");
- else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
- {
- if (!type || TREE_CODE (type) != FUNCTION_DECL)
- {
- pp_string (buffer, "access ");
- is_access = true;
- if (quals & TYPE_QUAL_CONST)
- pp_string (buffer, "constant ");
- else if (!name_only)
- pp_string (buffer, "all ");
- }
- else if (quals & TYPE_QUAL_CONST)
- pp_string (buffer, "in ");
- else
- {
- is_access = true;
- pp_string (buffer, "access ");
- /* ??? should be configurable: access or in out. */
- }
- }
- else
- {
- is_access = true;
- pp_string (buffer, "access ");
- if (!name_only)
- pp_string (buffer, "all ");
- }
- if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node))
- && type_name != NULL_TREE)
- dump_generic_ada_node
- (buffer, type_name,
- TREE_TYPE (node), spc, is_access, true);
- else
- dump_generic_ada_node
- (buffer, TREE_TYPE (node), TREE_TYPE (node),
- spc, 0, true);
- }
- }
- }
- break;
- case ARRAY_TYPE:
- if (name_only)
- dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, spc, limited_access, true);
- else
- dump_ada_array_type (buffer, node, spc);
- break;
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- if (name_only)
- {
- if (TYPE_NAME (node))
- dump_generic_ada_node
- (buffer, TYPE_NAME (node), node, spc, limited_access, true);
- else
- {
- pp_string (buffer, "anon_");
- pp_scalar (buffer, "%d", TYPE_UID (node));
- }
- }
- else
- print_ada_struct_decl (buffer, node, type, spc, true);
- break;
- case INTEGER_CST:
- /* We treat the upper half of the sizetype range as negative. This
- is consistent with the internal treatment and makes it possible
- to generate the (0 .. -1) range for flexible array members. */
- if (TREE_TYPE (node) == sizetype)
- node = fold_convert (ssizetype, node);
- if (tree_fits_shwi_p (node))
- pp_wide_integer (buffer, tree_to_shwi (node));
- else if (tree_fits_uhwi_p (node))
- pp_unsigned_wide_integer (buffer, tree_to_uhwi (node));
- else
- {
- wide_int val = node;
- int i;
- if (wi::neg_p (val))
- {
- pp_minus (buffer);
- val = -val;
- }
- sprintf (pp_buffer (buffer)->digit_buffer,
- "16#%" HOST_WIDE_INT_PRINT "x",
- val.elt (val.get_len () - 1));
- for (i = val.get_len () - 2; i >= 0; i--)
- sprintf (pp_buffer (buffer)->digit_buffer,
- HOST_WIDE_INT_PRINT_PADDED_HEX, val.elt (i));
- pp_string (buffer, pp_buffer (buffer)->digit_buffer);
- }
- break;
- case REAL_CST:
- case FIXED_CST:
- case COMPLEX_CST:
- case STRING_CST:
- case VECTOR_CST:
- return 0;
- case FUNCTION_DECL:
- case CONST_DECL:
- dump_ada_decl_name (buffer, node, limited_access);
- break;
- case TYPE_DECL:
- if (DECL_IS_BUILTIN (node))
- {
- /* Don't print the declaration of built-in types. */
- if (name_only)
- {
- /* If we're in the middle of a declaration, defaults to
- System.Address. */
- if (package_prefix)
- {
- append_withs ("System", false);
- pp_string (buffer, "System.Address");
- }
- else
- pp_string (buffer, "address");
- }
- break;
- }
- if (name_only)
- dump_ada_decl_name (buffer, node, limited_access);
- else
- {
- if (is_tagged_type (TREE_TYPE (node)))
- {
- tree tmp = TYPE_FIELDS (TREE_TYPE (node));
- int first = 1;
- /* Look for ancestors. */
- for (; tmp; tmp = TREE_CHAIN (tmp))
- {
- if (!DECL_NAME (tmp) && is_tagged_type (TREE_TYPE (tmp)))
- {
- if (first)
- {
- pp_string (buffer, "limited new ");
- first = 0;
- }
- else
- pp_string (buffer, " and ");
- dump_ada_decl_name
- (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
- }
- }
- pp_string (buffer, first ? "tagged limited " : " with ");
- }
- else if (has_nontrivial_methods (TREE_TYPE (node)))
- pp_string (buffer, "limited ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (node), type, spc, false, false);
- }
- break;
- case VAR_DECL:
- case PARM_DECL:
- case FIELD_DECL:
- case NAMESPACE_DECL:
- dump_ada_decl_name (buffer, node, false);
- break;
- default:
- /* Ignore other nodes (e.g. expressions). */
- return 0;
- }
- return 1;
- }
- /* Dump in BUFFER NODE's methods. SPC is the indentation level. Return 1 if
- methods were printed, 0 otherwise.
- We do it in 2 passes: first, the regular methods, i.e. non-static member
- functions, are output immediately within the package created for the class
- so that they are considered as primitive operations in Ada; second, the
- static member functions are output in a nested package so that they are
- _not_ considered as primitive operations in Ada.
- This approach is necessary because the formers have the implicit 'this'
- pointer whereas the latters don't and, on 32-bit x86/Windows, the calling
- conventions for the 'this' pointer are special. Therefore, the compiler
- needs to be able to differentiate regular methods (with 'this' pointer)
- from static member functions that take a pointer to the class as first
- parameter. */
- static int
- print_ada_methods (pretty_printer *buffer, tree node, int spc)
- {
- bool has_static_methods = false;
- tree t;
- int res;
- if (!has_nontrivial_methods (node))
- return 0;
- pp_semicolon (buffer);
- /* First pass: the regular methods. */
- res = 1;
- for (t = TYPE_METHODS (node); t; t = TREE_CHAIN (t))
- {
- if (TREE_CODE (TREE_TYPE (t)) != METHOD_TYPE)
- {
- has_static_methods = true;
- continue;
- }
- if (res)
- {
- pp_newline (buffer);
- pp_newline (buffer);
- }
- res = print_ada_declaration (buffer, t, node, spc);
- }
- if (!has_static_methods)
- return 1;
- pp_newline (buffer);
- newline_and_indent (buffer, spc);
- /* Second pass: the static member functions. */
- pp_string (buffer, "package Static is");
- pp_newline (buffer);
- spc += INDENT_INCR;
- res = 0;
- for (t = TYPE_METHODS (node); t; t = TREE_CHAIN (t))
- {
- if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
- continue;
- if (res)
- {
- pp_newline (buffer);
- pp_newline (buffer);
- }
- res = print_ada_declaration (buffer, t, node, spc);
- }
- spc -= INDENT_INCR;
- newline_and_indent (buffer, spc);
- pp_string (buffer, "end;");
- /* In order to save the clients from adding a second use clause for the
- nested package, we generate renamings for the static member functions
- in the package created for the class. */
- for (t = TYPE_METHODS (node); t; t = TREE_CHAIN (t))
- {
- bool is_function;
- if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
- continue;
- pp_newline (buffer);
- newline_and_indent (buffer, spc);
- if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))))
- {
- pp_string (buffer, "procedure ");
- is_function = false;
- }
- else
- {
- pp_string (buffer, "function ");
- is_function = true;
- }
- dump_ada_decl_name (buffer, t, false);
- dump_ada_function_declaration (buffer, t, false, false, false, spc);
- if (is_function)
- {
- pp_string (buffer, " return ");
- dump_generic_ada_node (buffer, TREE_TYPE (TREE_TYPE (t)), node,
- spc, false, true);
- }
- pp_string (buffer, " renames Static.");
- dump_ada_decl_name (buffer, t, false);
- pp_semicolon (buffer);
- }
- return 1;
- }
- /* Dump in BUFFER anonymous types nested inside T's definition.
- PARENT is the parent node of T.
- FORWARD indicates whether a forward declaration of T should be generated.
- SPC is the indentation level. */
- static void
- dump_nested_types (pretty_printer *buffer, tree t, tree parent, bool forward,
- int spc)
- {
- tree field, outer, decl;
- /* Avoid recursing over the same tree. */
- if (TREE_VISITED (t))
- return;
- /* Find possible anonymous arrays/unions/structs recursively. */
- outer = TREE_TYPE (t);
- if (outer == NULL_TREE)
- return;
- if (forward)
- {
- pp_string (buffer, "type ");
- dump_generic_ada_node (buffer, t, t, spc, false, true);
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- TREE_VISITED (t) = 1;
- }
- field = TYPE_FIELDS (outer);
- while (field)
- {
- if ((TREE_TYPE (field) != outer
- || (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE
- && TREE_TYPE (TREE_TYPE (field)) != outer))
- && (!TYPE_NAME (TREE_TYPE (field))
- || (TREE_CODE (field) == TYPE_DECL
- && DECL_NAME (field) != DECL_NAME (t)
- && TYPE_NAME (TREE_TYPE (field)) != TYPE_NAME (outer))))
- {
- switch (TREE_CODE (TREE_TYPE (field)))
- {
- case POINTER_TYPE:
- decl = TREE_TYPE (TREE_TYPE (field));
- if (TREE_CODE (decl) == FUNCTION_TYPE)
- for (decl = TREE_TYPE (decl);
- decl && TREE_CODE (decl) == POINTER_TYPE;
- decl = TREE_TYPE (decl))
- ;
- decl = get_underlying_decl (decl);
- if (decl
- && DECL_P (decl)
- && decl_sloc (decl, true) > decl_sloc (t, true)
- && DECL_SOURCE_FILE (decl) == DECL_SOURCE_FILE (t)
- && !TREE_VISITED (decl)
- && !DECL_IS_BUILTIN (decl)
- && (!RECORD_OR_UNION_TYPE_P (TREE_TYPE (decl))
- || TYPE_FIELDS (TREE_TYPE (decl))))
- {
- /* Generate forward declaration. */
- pp_string (buffer, "type ");
- dump_generic_ada_node (buffer, decl, 0, spc, false, true);
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- /* Ensure we do not generate duplicate forward
- declarations for this type. */
- TREE_VISITED (decl) = 1;
- }
- break;
- case ARRAY_TYPE:
- /* Special case char arrays. */
- if (is_char_array (field))
- pp_string (buffer, "sub");
- pp_string (buffer, "type ");
- dump_ada_double_name (buffer, parent, field, "_array is ");
- dump_ada_array_type (buffer, field, spc);
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- break;
- case UNION_TYPE:
- TREE_VISITED (t) = 1;
- dump_nested_types (buffer, field, t, false, spc);
- pp_string (buffer, "type ");
- if (TYPE_NAME (TREE_TYPE (field)))
- {
- dump_generic_ada_node
- (buffer, TYPE_NAME (TREE_TYPE (field)), 0, spc, false,
- true);
- pp_string (buffer, " (discr : unsigned := 0) is ");
- print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, spc, false);
- pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, spc, false, true);
- pp_string (buffer, ");");
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Unchecked_Union (");
- dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, spc, false, true);
- pp_string (buffer, ");");
- }
- else
- {
- dump_ada_double_name
- (buffer, parent, field,
- "_union (discr : unsigned := 0) is ");
- print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, spc, false);
- pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
- dump_ada_double_name (buffer, parent, field, "_union);");
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Unchecked_Union (");
- dump_ada_double_name (buffer, parent, field, "_union);");
- }
- newline_and_indent (buffer, spc);
- break;
- case RECORD_TYPE:
- if (TYPE_NAME (TREE_TYPE (t)) && !TREE_VISITED (t))
- {
- pp_string (buffer, "type ");
- dump_generic_ada_node
- (buffer, t, parent, spc, false, true);
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- }
- TREE_VISITED (t) = 1;
- dump_nested_types (buffer, field, t, false, spc);
- pp_string (buffer, "type ");
- if (TYPE_NAME (TREE_TYPE (field)))
- {
- dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, spc, false, true);
- pp_string (buffer, " is ");
- print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, spc, false);
- pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (field), 0, spc, false, true);
- pp_string (buffer, ");");
- }
- else
- {
- dump_ada_double_name
- (buffer, parent, field, "_struct is ");
- print_ada_struct_decl
- (buffer, TREE_TYPE (field), t, spc, false);
- pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
- dump_ada_double_name (buffer, parent, field, "_struct);");
- }
- newline_and_indent (buffer, spc);
- break;
- default:
- break;
- }
- }
- field = TREE_CHAIN (field);
- }
- TREE_VISITED (t) = 1;
- }
- /* Dump in BUFFER constructor spec corresponding to T. */
- static void
- print_constructor (pretty_printer *buffer, tree t)
- {
- tree decl_name = DECL_NAME (DECL_ORIGIN (t));
- pp_string (buffer, "New_");
- pp_ada_tree_identifier (buffer, decl_name, t, false);
- }
- /* Dump in BUFFER destructor spec corresponding to T. */
- static void
- print_destructor (pretty_printer *buffer, tree t)
- {
- tree decl_name = DECL_NAME (DECL_ORIGIN (t));
- pp_string (buffer, "Delete_");
- pp_ada_tree_identifier (buffer, decl_name, t, false);
- }
- /* Return the name of type T. */
- static const char *
- type_name (tree t)
- {
- tree n = TYPE_NAME (t);
- if (TREE_CODE (n) == IDENTIFIER_NODE)
- return IDENTIFIER_POINTER (n);
- else
- return IDENTIFIER_POINTER (DECL_NAME (n));
- }
- /* Print in BUFFER the declaration of a variable T of type TYPE in Ada syntax.
- SPC is the indentation level. Return 1 if a declaration was printed,
- 0 otherwise. */
- static int
- print_ada_declaration (pretty_printer *buffer, tree t, tree type, int spc)
- {
- int is_var = 0, need_indent = 0;
- int is_class = false;
- tree name = TYPE_NAME (TREE_TYPE (t));
- tree decl_name = DECL_NAME (t);
- tree orig = NULL_TREE;
- if (cpp_check && cpp_check (t, IS_TEMPLATE))
- return dump_ada_template (buffer, t, spc);
- if (TREE_CODE (t) == CONST_DECL && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
- /* Skip enumeral values: will be handled as part of the type itself. */
- return 0;
- if (TREE_CODE (t) == TYPE_DECL)
- {
- orig = DECL_ORIGINAL_TYPE (t);
- if (orig && TYPE_STUB_DECL (orig))
- {
- tree stub = TYPE_STUB_DECL (orig);
- tree typ = TREE_TYPE (stub);
- if (TYPE_NAME (typ))
- {
- /* If types have same representation, and same name (ignoring
- casing), then ignore the second type. */
- if (type_name (typ) == type_name (TREE_TYPE (t))
- || !strcasecmp (type_name (typ), type_name (TREE_TYPE (t))))
- return 0;
- INDENT (spc);
- if (RECORD_OR_UNION_TYPE_P (typ) && !TYPE_FIELDS (typ))
- {
- pp_string (buffer, "-- skipped empty struct ");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- }
- else
- {
- if (!TREE_VISITED (stub)
- && DECL_SOURCE_FILE (stub) == source_file_base)
- dump_nested_types (buffer, stub, stub, true, spc);
- pp_string (buffer, "subtype ");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- pp_string (buffer, " is ");
- dump_generic_ada_node (buffer, typ, type, spc, false, true);
- pp_semicolon (buffer);
- }
- return 1;
- }
- }
- /* Skip unnamed or anonymous structs/unions/enum types. */
- if (!orig && !decl_name && !name)
- {
- tree tmp;
- location_t sloc;
- if (cpp_check || TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE)
- return 0;
- if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
- {
- /* Search next items until finding a named type decl. */
- sloc = decl_sloc_common (t, true, true);
- for (tmp = TREE_CHAIN (t); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (TREE_CODE (tmp) == TYPE_DECL
- && (DECL_NAME (tmp) || TYPE_NAME (TREE_TYPE (tmp))))
- {
- /* If same sloc, it means we can ignore the anonymous
- struct. */
- if (decl_sloc_common (tmp, true, true) == sloc)
- return 0;
- else
- break;
- }
- }
- if (tmp == NULL)
- return 0;
- }
- }
- if (!orig
- && TREE_CODE (TREE_TYPE (t)) == ENUMERAL_TYPE
- && decl_name
- && (*IDENTIFIER_POINTER (decl_name) == '.'
- || *IDENTIFIER_POINTER (decl_name) == '$'))
- /* Skip anonymous enum types (duplicates of real types). */
- return 0;
- INDENT (spc);
- switch (TREE_CODE (TREE_TYPE (t)))
- {
- case RECORD_TYPE:
- case UNION_TYPE:
- case QUAL_UNION_TYPE:
- /* Skip empty structs (typically forward references to real
- structs). */
- if (!TYPE_FIELDS (TREE_TYPE (t)))
- {
- pp_string (buffer, "-- skipped empty struct ");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- return 1;
- }
- if (decl_name
- && (*IDENTIFIER_POINTER (decl_name) == '.'
- || *IDENTIFIER_POINTER (decl_name) == '$'))
- {
- pp_string (buffer, "-- skipped anonymous struct ");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- TREE_VISITED (t) = 1;
- return 1;
- }
- if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
- pp_string (buffer, "subtype ");
- else
- {
- dump_nested_types (buffer, t, t, false, spc);
- if (separate_class_package (t))
- {
- is_class = true;
- pp_string (buffer, "package Class_");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- pp_string (buffer, " is");
- spc += INDENT_INCR;
- newline_and_indent (buffer, spc);
- }
- pp_string (buffer, "type ");
- }
- break;
- case ARRAY_TYPE:
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
- || is_char_array (t))
- pp_string (buffer, "subtype ");
- else
- pp_string (buffer, "type ");
- break;
- case FUNCTION_TYPE:
- pp_string (buffer, "-- skipped function type ");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- return 1;
- break;
- case ENUMERAL_TYPE:
- if ((orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
- || !is_simple_enum (TREE_TYPE (t)))
- pp_string (buffer, "subtype ");
- else
- pp_string (buffer, "type ");
- break;
- default:
- pp_string (buffer, "subtype ");
- }
- TREE_VISITED (t) = 1;
- }
- else
- {
- if (TREE_CODE (t) == VAR_DECL
- && decl_name
- && *IDENTIFIER_POINTER (decl_name) == '_')
- return 0;
- need_indent = 1;
- }
- /* Print the type and name. */
- if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
- {
- if (need_indent)
- INDENT (spc);
- /* Print variable's name. */
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- if (TREE_CODE (t) == TYPE_DECL)
- {
- pp_string (buffer, " is ");
- if (orig && TYPE_NAME (orig) && orig != TREE_TYPE (t))
- dump_generic_ada_node
- (buffer, TYPE_NAME (orig), type, spc, false, true);
- else
- dump_ada_array_type (buffer, t, spc);
- }
- else
- {
- tree tmp = TYPE_NAME (TREE_TYPE (t));
- if (spc == INDENT_INCR || TREE_STATIC (t))
- is_var = 1;
- pp_string (buffer, " : ");
- if (tmp)
- {
- if (TREE_CODE (TREE_TYPE (tmp)) != POINTER_TYPE
- && TREE_CODE (tmp) != INTEGER_TYPE)
- pp_string (buffer, "aliased ");
- dump_generic_ada_node (buffer, tmp, type, spc, false, true);
- }
- else
- {
- pp_string (buffer, "aliased ");
- if (!type)
- dump_ada_array_type (buffer, t, spc);
- else
- dump_ada_double_name (buffer, type, t, "_array");
- }
- }
- }
- else if (TREE_CODE (t) == FUNCTION_DECL)
- {
- bool is_function, is_abstract_class = false;
- bool is_method = TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE;
- tree decl_name = DECL_NAME (t);
- bool is_abstract = false;
- bool is_constructor = false;
- bool is_destructor = false;
- bool is_copy_constructor = false;
- if (!decl_name)
- return 0;
- if (cpp_check)
- {
- is_abstract = cpp_check (t, IS_ABSTRACT);
- is_constructor = cpp_check (t, IS_CONSTRUCTOR);
- is_destructor = cpp_check (t, IS_DESTRUCTOR);
- is_copy_constructor = cpp_check (t, IS_COPY_CONSTRUCTOR);
- }
- /* Skip copy constructors: some are internal only, and those that are
- not cannot be called easily from Ada anyway. */
- if (is_copy_constructor)
- return 0;
- if (is_constructor || is_destructor)
- {
- /* Only consider constructors/destructors for complete objects. */
- if (strncmp (IDENTIFIER_POINTER (decl_name), "__comp", 6) != 0)
- return 0;
- }
- /* If this function has an entry in the vtable, we cannot omit it. */
- else if (!DECL_VINDEX (t) && *IDENTIFIER_POINTER (decl_name) == '_')
- {
- INDENT (spc);
- pp_string (buffer, "-- skipped func ");
- pp_string (buffer, IDENTIFIER_POINTER (decl_name));
- return 1;
- }
- if (need_indent)
- INDENT (spc);
- if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (t))) && !is_constructor)
- {
- pp_string (buffer, "procedure ");
- is_function = false;
- }
- else
- {
- pp_string (buffer, "function ");
- is_function = true;
- }
- if (is_constructor)
- print_constructor (buffer, t);
- else if (is_destructor)
- print_destructor (buffer, t);
- else
- dump_ada_decl_name (buffer, t, false);
- dump_ada_function_declaration
- (buffer, t, is_method, is_constructor, is_destructor, spc);
- if (is_function)
- {
- pp_string (buffer, " return ");
- tree ret_type
- = is_constructor ? DECL_CONTEXT (t) : TREE_TYPE (TREE_TYPE (t));
- dump_generic_ada_node (buffer, ret_type, type, spc, false, true);
- }
- if (is_constructor
- && RECORD_OR_UNION_TYPE_P (type)
- && TYPE_METHODS (type))
- {
- tree tmp;
- for (tmp = TYPE_METHODS (type); tmp; tmp = TREE_CHAIN (tmp))
- if (cpp_check (tmp, IS_ABSTRACT))
- {
- is_abstract_class = true;
- break;
- }
- }
- if (is_abstract || is_abstract_class)
- pp_string (buffer, " is abstract");
- pp_semicolon (buffer);
- pp_string (buffer, " -- ");
- dump_sloc (buffer, t);
- if (is_abstract || !DECL_ASSEMBLER_NAME (t))
- return 1;
- newline_and_indent (buffer, spc);
- if (is_constructor)
- {
- pp_string (buffer, "pragma CPP_Constructor (");
- print_constructor (buffer, t);
- pp_string (buffer, ", \"");
- pp_asm_name (buffer, t);
- pp_string (buffer, "\");");
- }
- else if (is_destructor)
- {
- pp_string (buffer, "pragma Import (CPP, ");
- print_destructor (buffer, t);
- pp_string (buffer, ", \"");
- pp_asm_name (buffer, t);
- pp_string (buffer, "\");");
- }
- else
- {
- dump_ada_import (buffer, t);
- }
- return 1;
- }
- else if (TREE_CODE (t) == TYPE_DECL && !DECL_ORIGINAL_TYPE (t))
- {
- int is_interface = 0;
- int is_abstract_record = 0;
- if (need_indent)
- INDENT (spc);
- /* Anonymous structs/unions */
- dump_generic_ada_node (buffer, TREE_TYPE (t), t, spc, false, true);
- if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
- || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE)
- {
- pp_string (buffer, " (discr : unsigned := 0)");
- }
- pp_string (buffer, " is ");
- /* Check whether we have an Ada interface compatible class. */
- if (cpp_check
- && RECORD_OR_UNION_TYPE_P (TREE_TYPE (t))
- && TYPE_METHODS (TREE_TYPE (t)))
- {
- int num_fields = 0;
- tree tmp;
- /* Check that there are no fields other than the virtual table. */
- for (tmp = TYPE_FIELDS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (TREE_CODE (tmp) == TYPE_DECL)
- continue;
- num_fields++;
- }
- if (num_fields == 1)
- is_interface = 1;
- /* Also check that there are only virtual methods. */
- for (tmp = TYPE_METHODS (TREE_TYPE (t)); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (cpp_check (tmp, IS_ABSTRACT))
- is_abstract_record = 1;
- else
- is_interface = 0;
- }
- }
- TREE_VISITED (t) = 1;
- if (is_interface)
- {
- pp_string (buffer, "limited interface; -- ");
- dump_sloc (buffer, t);
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Import (CPP, ");
- dump_generic_ada_node
- (buffer, TYPE_NAME (TREE_TYPE (t)), type, spc, false, true);
- pp_right_paren (buffer);
- print_ada_methods (buffer, TREE_TYPE (t), spc);
- }
- else
- {
- if (is_abstract_record)
- pp_string (buffer, "abstract ");
- dump_generic_ada_node (buffer, t, t, spc, false, false);
- }
- }
- else
- {
- if (need_indent)
- INDENT (spc);
- if (TREE_CODE (t) == FIELD_DECL && DECL_NAME (t))
- check_name (buffer, t);
- /* Print variable/type's name. */
- dump_generic_ada_node (buffer, t, t, spc, false, true);
- if (TREE_CODE (t) == TYPE_DECL)
- {
- tree orig = DECL_ORIGINAL_TYPE (t);
- int is_subtype = orig && TYPE_NAME (orig) && orig != TREE_TYPE (t);
- if (!is_subtype
- && (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
- || TREE_CODE (TREE_TYPE (t)) == QUAL_UNION_TYPE))
- pp_string (buffer, " (discr : unsigned := 0)");
- pp_string (buffer, " is ");
- dump_generic_ada_node (buffer, orig, t, spc, false, is_subtype);
- }
- else
- {
- if (spc == INDENT_INCR || TREE_STATIC (t))
- is_var = 1;
- pp_string (buffer, " : ");
- /* Print type declaration. */
- if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
- && !TYPE_NAME (TREE_TYPE (t)))
- {
- dump_ada_double_name (buffer, type, t, "_union");
- }
- else if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (t)))
- {
- if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
- pp_string (buffer, "aliased ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (t), t, spc, false, true);
- }
- else
- {
- if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE
- && (TYPE_NAME (TREE_TYPE (t))
- || TREE_CODE (TREE_TYPE (t)) != INTEGER_TYPE))
- pp_string (buffer, "aliased ");
- dump_generic_ada_node
- (buffer, TREE_TYPE (t), TREE_TYPE (t), spc, false, true);
- }
- }
- }
- if (is_class)
- {
- spc -= INDENT_INCR;
- newline_and_indent (buffer, spc);
- pp_string (buffer, "end;");
- newline_and_indent (buffer, spc);
- pp_string (buffer, "use Class_");
- dump_generic_ada_node (buffer, t, type, spc, false, true);
- pp_semicolon (buffer);
- pp_newline (buffer);
- /* All needed indentation/newline performed already, so return 0. */
- return 0;
- }
- else
- {
- pp_string (buffer, "; -- ");
- dump_sloc (buffer, t);
- }
- if (is_var)
- {
- newline_and_indent (buffer, spc);
- dump_ada_import (buffer, t);
- }
- return 1;
- }
- /* Prints in BUFFER a structure NODE of type TYPE: name, fields, and methods
- with Ada syntax. SPC is the indentation level. If DISPLAY_CONVENTION is
- true, also print the pragma Convention for NODE. */
- static void
- print_ada_struct_decl (pretty_printer *buffer, tree node, tree type, int spc,
- bool display_convention)
- {
- tree tmp;
- const bool is_union
- = TREE_CODE (node) == UNION_TYPE || TREE_CODE (node) == QUAL_UNION_TYPE;
- char buf[32];
- int field_num = 0;
- int field_spc = spc + INDENT_INCR;
- int need_semicolon;
- bitfield_used = false;
- if (!TYPE_FIELDS (node))
- pp_string (buffer, "null record;");
- else
- {
- pp_string (buffer, "record");
- /* Print the contents of the structure. */
- if (is_union)
- {
- newline_and_indent (buffer, spc + INDENT_INCR);
- pp_string (buffer, "case discr is");
- field_spc = spc + INDENT_INCR * 3;
- }
- pp_newline (buffer);
- /* Print the non-static fields of the structure. */
- for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
- {
- /* Add parent field if needed. */
- if (!DECL_NAME (tmp))
- {
- if (!is_tagged_type (TREE_TYPE (tmp)))
- {
- if (!TYPE_NAME (TREE_TYPE (tmp)))
- print_ada_declaration (buffer, tmp, type, field_spc);
- else
- {
- INDENT (field_spc);
- if (field_num == 0)
- pp_string (buffer, "parent : aliased ");
- else
- {
- sprintf (buf, "field_%d : aliased ", field_num + 1);
- pp_string (buffer, buf);
- }
- dump_ada_decl_name
- (buffer, TYPE_NAME (TREE_TYPE (tmp)), false);
- pp_semicolon (buffer);
- }
- pp_newline (buffer);
- field_num++;
- }
- }
- /* Avoid printing the structure recursively. */
- else if ((TREE_TYPE (tmp) != node
- || (TREE_CODE (TREE_TYPE (tmp)) == POINTER_TYPE
- && TREE_TYPE (TREE_TYPE (tmp)) != node))
- && TREE_CODE (tmp) != TYPE_DECL
- && !TREE_STATIC (tmp))
- {
- /* Skip internal virtual table field. */
- if (strncmp (IDENTIFIER_POINTER (DECL_NAME (tmp)), "_vptr", 5))
- {
- if (is_union)
- {
- if (TREE_CHAIN (tmp)
- && TREE_TYPE (TREE_CHAIN (tmp)) != node
- && TREE_CODE (TREE_CHAIN (tmp)) != TYPE_DECL)
- sprintf (buf, "when %d =>", field_num);
- else
- sprintf (buf, "when others =>");
- INDENT (spc + INDENT_INCR * 2);
- pp_string (buffer, buf);
- pp_newline (buffer);
- }
- if (print_ada_declaration (buffer, tmp, type, field_spc))
- {
- pp_newline (buffer);
- field_num++;
- }
- }
- }
- }
- if (is_union)
- {
- INDENT (spc + INDENT_INCR);
- pp_string (buffer, "end case;");
- pp_newline (buffer);
- }
- if (field_num == 0)
- {
- INDENT (spc + INDENT_INCR);
- pp_string (buffer, "null;");
- pp_newline (buffer);
- }
- INDENT (spc);
- pp_string (buffer, "end record;");
- }
- newline_and_indent (buffer, spc);
- if (!display_convention)
- return;
- if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (type)))
- {
- if (has_nontrivial_methods (TREE_TYPE (type)))
- pp_string (buffer, "pragma Import (CPP, ");
- else
- pp_string (buffer, "pragma Convention (C_Pass_By_Copy, ");
- }
- else
- pp_string (buffer, "pragma Convention (C, ");
- package_prefix = false;
- dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
- package_prefix = true;
- pp_right_paren (buffer);
- if (is_union)
- {
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Unchecked_Union (");
- dump_generic_ada_node (buffer, TREE_TYPE (type), type, spc, false, true);
- pp_right_paren (buffer);
- }
- if (bitfield_used)
- {
- pp_semicolon (buffer);
- newline_and_indent (buffer, spc);
- pp_string (buffer, "pragma Pack (");
- dump_generic_ada_node
- (buffer, TREE_TYPE (type), type, spc, false, true);
- pp_right_paren (buffer);
- bitfield_used = false;
- }
- need_semicolon = !print_ada_methods (buffer, node, spc);
- /* Print the static fields of the structure, if any. */
- for (tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp))
- {
- if (DECL_NAME (tmp) && TREE_STATIC (tmp))
- {
- if (need_semicolon)
- {
- need_semicolon = false;
- pp_semicolon (buffer);
- }
- pp_newline (buffer);
- pp_newline (buffer);
- print_ada_declaration (buffer, tmp, type, spc);
- }
- }
- }
- /* Dump all the declarations in SOURCE_FILE to an Ada spec.
- COLLECT_ALL_REFS is a front-end callback used to collect all relevant
- nodes for SOURCE_FILE. CHECK is used to perform C++ queries on nodes. */
- static void
- dump_ads (const char *source_file,
- void (*collect_all_refs)(const char *),
- int (*check)(tree, cpp_operation))
- {
- char *ads_name;
- char *pkg_name;
- char *s;
- FILE *f;
- pkg_name = get_ada_package (source_file);
- /* Construct the .ads filename and package name. */
- ads_name = xstrdup (pkg_name);
- for (s = ads_name; *s; s++)
- if (*s == '.')
- *s = '-';
- else
- *s = TOLOWER (*s);
- ads_name = reconcat (ads_name, ads_name, ".ads", NULL);
- /* Write out the .ads file. */
- f = fopen (ads_name, "w");
- if (f)
- {
- pretty_printer pp;
- pp_needs_newline (&pp) = true;
- pp.buffer->stream = f;
- /* Dump all relevant macros. */
- dump_ada_macros (&pp, source_file);
- /* Reset the table of withs for this file. */
- reset_ada_withs ();
- (*collect_all_refs) (source_file);
- /* Dump all references. */
- cpp_check = check;
- dump_ada_nodes (&pp, source_file);
- /* Requires Ada 2005 syntax, so generate corresponding pragma.
- Also, disable style checks since this file is auto-generated. */
- fprintf (f, "pragma Ada_2005;\npragma Style_Checks (Off);\n\n");
- /* Dump withs. */
- dump_ada_withs (f);
- fprintf (f, "\npackage %s is\n\n", pkg_name);
- pp_write_text_to_stream (&pp);
- /* ??? need to free pp */
- fprintf (f, "end %s;\n", pkg_name);
- fclose (f);
- }
- free (ads_name);
- free (pkg_name);
- }
- static const char **source_refs = NULL;
- static int source_refs_used = 0;
- static int source_refs_allocd = 0;
- /* Add an entry for FILENAME to the table SOURCE_REFS. */
- void
- collect_source_ref (const char *filename)
- {
- int i;
- if (!filename)
- return;
- if (source_refs_allocd == 0)
- {
- source_refs_allocd = 1024;
- source_refs = XNEWVEC (const char *, source_refs_allocd);
- }
- for (i = 0; i < source_refs_used; i++)
- if (filename == source_refs[i])
- return;
- if (source_refs_used == source_refs_allocd)
- {
- source_refs_allocd *= 2;
- source_refs = XRESIZEVEC (const char *, source_refs, source_refs_allocd);
- }
- source_refs[source_refs_used++] = filename;
- }
- /* Main entry point: dump all Ada specs corresponding to SOURCE_REFS
- using callbacks COLLECT_ALL_REFS and CHECK.
- COLLECT_ALL_REFS is a front-end callback used to collect all relevant
- nodes for a given source file.
- CHECK is used to perform C++ queries on nodes, or NULL for the C
- front-end. */
- void
- dump_ada_specs (void (*collect_all_refs)(const char *),
- int (*check)(tree, cpp_operation))
- {
- int i;
- /* Iterate over the list of files to dump specs for */
- for (i = 0; i < source_refs_used; i++)
- dump_ads (source_refs[i], collect_all_refs, check);
- /* Free files table. */
- free (source_refs);
- }
|