pretty-print.c.orig 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628
  1. /* Various declarations for language-independent pretty-print subroutines.
  2. Copyright (C) 2003-2020 Free Software Foundation, Inc.
  3. Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
  4. This file is part of GCC.
  5. GCC is free software; you can redistribute it and/or modify it under
  6. the terms of the GNU General Public License as published by the Free
  7. Software Foundation; either version 3, or (at your option) any later
  8. version.
  9. GCC is distributed in the hope that it will be useful, but WITHOUT ANY
  10. WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with GCC; see the file COPYING3. If not see
  15. <http://www.gnu.org/licenses/>. */
  16. #include "config.h"
  17. #include "system.h"
  18. #include "coretypes.h"
  19. #include "intl.h"
  20. #include "pretty-print.h"
  21. #include "diagnostic-color.h"
  22. #include "diagnostic-event-id.h"
  23. #include "selftest.h"
  24. #if HAVE_ICONV
  25. #include <iconv.h>
  26. #endif
  27. #ifdef __MINGW32__
  28. /* Replacement for fputs() that handles ANSI escape codes on Windows NT.
  29. Contributed by: Liu Hao (lh_mouse at 126 dot com)
  30. XXX: This file is compiled into libcommon.a that will be self-contained.
  31. It looks like that these functions can be put nowhere else. */
  32. #include <io.h>
  33. #define WIN32_LEAN_AND_MEAN 1
  34. #include <windows.h>
  35. /* Write all bytes in [s,s+n) into the specified stream.
  36. Errors are ignored. */
  37. static void
  38. write_all (HANDLE h, const char *s, size_t n)
  39. {
  40. size_t rem = n;
  41. DWORD step;
  42. while (rem != 0)
  43. {
  44. if (rem <= UINT_MAX)
  45. step = rem;
  46. else
  47. step = UINT_MAX;
  48. if (!WriteFile (h, s + n - rem, step, &step, NULL))
  49. break;
  50. rem -= step;
  51. }
  52. }
  53. /* Find the beginning of an escape sequence.
  54. There are two cases:
  55. 1. If the sequence begins with an ESC character (0x1B) and a second
  56. character X in [0x40,0x5F], returns X and stores a pointer to
  57. the third character into *head.
  58. 2. If the sequence begins with a character X in [0x80,0x9F], returns
  59. (X-0x40) and stores a pointer to the second character into *head.
  60. Stores the number of ESC character(s) in *prefix_len.
  61. Returns 0 if no such sequence can be found. */
  62. static int
  63. find_esc_head (int *prefix_len, const char **head, const char *str)
  64. {
  65. int c;
  66. const char *r = str;
  67. int escaped = 0;
  68. for (;;)
  69. {
  70. c = (unsigned char) *r;
  71. if (c == 0)
  72. {
  73. /* Not found. */
  74. return 0;
  75. }
  76. if (escaped && 0x40 <= c && c <= 0x5F)
  77. {
  78. /* Found (case 1). */
  79. *prefix_len = 2;
  80. *head = r + 1;
  81. return c;
  82. }
  83. if (0x80 <= c && c <= 0x9F)
  84. {
  85. /* Found (case 2). */
  86. *prefix_len = 1;
  87. *head = r + 1;
  88. return c - 0x40;
  89. }
  90. ++r;
  91. escaped = c == 0x1B;
  92. }
  93. }
  94. /* Find the terminator of an escape sequence.
  95. str should be the value stored in *head by a previous successful
  96. call to find_esc_head().
  97. Returns 0 if no such sequence can be found. */
  98. static int
  99. find_esc_terminator (const char **term, const char *str)
  100. {
  101. int c;
  102. const char *r = str;
  103. for (;;)
  104. {
  105. c = (unsigned char) *r;
  106. if (c == 0)
  107. {
  108. /* Not found. */
  109. return 0;
  110. }
  111. if (0x40 <= c && c <= 0x7E)
  112. {
  113. /* Found. */
  114. *term = r;
  115. return c;
  116. }
  117. ++r;
  118. }
  119. }
  120. /* Handle a sequence of codes. Sequences that are invalid, reserved,
  121. unrecognized or unimplemented are ignored silently.
  122. There isn't much we can do because of lameness of Windows consoles. */
  123. static void
  124. eat_esc_sequence (HANDLE h, int esc_code,
  125. const char *esc_head, const char *esc_term)
  126. {
  127. /* Numbers in an escape sequence cannot be negative, because
  128. a minus sign in the middle of it would have terminated it. */
  129. long n1, n2;
  130. char *eptr, *delim;
  131. CONSOLE_SCREEN_BUFFER_INFO sb;
  132. COORD cr;
  133. /* ED and EL parameters. */
  134. DWORD cnt, step;
  135. long rows;
  136. /* SGR parameters. */
  137. WORD attrib_add, attrib_rm;
  138. const char *param;
  139. switch (MAKEWORD (esc_code, *esc_term))
  140. {
  141. /* ESC [ n1 'A'
  142. Move the cursor up by n1 characters. */
  143. case MAKEWORD ('[', 'A'):
  144. if (esc_head == esc_term)
  145. n1 = 1;
  146. else
  147. {
  148. n1 = strtol (esc_head, &eptr, 10);
  149. if (eptr != esc_term)
  150. break;
  151. }
  152. if (GetConsoleScreenBufferInfo (h, &sb))
  153. {
  154. cr = sb.dwCursorPosition;
  155. /* Stop at the topmost boundary. */
  156. if (cr.Y > n1)
  157. cr.Y -= n1;
  158. else
  159. cr.Y = 0;
  160. SetConsoleCursorPosition (h, cr);
  161. }
  162. break;
  163. /* ESC [ n1 'B'
  164. Move the cursor down by n1 characters. */
  165. case MAKEWORD ('[', 'B'):
  166. if (esc_head == esc_term)
  167. n1 = 1;
  168. else
  169. {
  170. n1 = strtol (esc_head, &eptr, 10);
  171. if (eptr != esc_term)
  172. break;
  173. }
  174. if (GetConsoleScreenBufferInfo (h, &sb))
  175. {
  176. cr = sb.dwCursorPosition;
  177. /* Stop at the bottommost boundary. */
  178. if (sb.dwSize.Y - cr.Y > n1)
  179. cr.Y += n1;
  180. else
  181. cr.Y = sb.dwSize.Y;
  182. SetConsoleCursorPosition (h, cr);
  183. }
  184. break;
  185. /* ESC [ n1 'C'
  186. Move the cursor right by n1 characters. */
  187. case MAKEWORD ('[', 'C'):
  188. if (esc_head == esc_term)
  189. n1 = 1;
  190. else
  191. {
  192. n1 = strtol (esc_head, &eptr, 10);
  193. if (eptr != esc_term)
  194. break;
  195. }
  196. if (GetConsoleScreenBufferInfo (h, &sb))
  197. {
  198. cr = sb.dwCursorPosition;
  199. /* Stop at the rightmost boundary. */
  200. if (sb.dwSize.X - cr.X > n1)
  201. cr.X += n1;
  202. else
  203. cr.X = sb.dwSize.X;
  204. SetConsoleCursorPosition (h, cr);
  205. }
  206. break;
  207. /* ESC [ n1 'D'
  208. Move the cursor left by n1 characters. */
  209. case MAKEWORD ('[', 'D'):
  210. if (esc_head == esc_term)
  211. n1 = 1;
  212. else
  213. {
  214. n1 = strtol (esc_head, &eptr, 10);
  215. if (eptr != esc_term)
  216. break;
  217. }
  218. if (GetConsoleScreenBufferInfo (h, &sb))
  219. {
  220. cr = sb.dwCursorPosition;
  221. /* Stop at the leftmost boundary. */
  222. if (cr.X > n1)
  223. cr.X -= n1;
  224. else
  225. cr.X = 0;
  226. SetConsoleCursorPosition (h, cr);
  227. }
  228. break;
  229. /* ESC [ n1 'E'
  230. Move the cursor to the beginning of the n1-th line downwards. */
  231. case MAKEWORD ('[', 'E'):
  232. if (esc_head == esc_term)
  233. n1 = 1;
  234. else
  235. {
  236. n1 = strtol (esc_head, &eptr, 10);
  237. if (eptr != esc_term)
  238. break;
  239. }
  240. if (GetConsoleScreenBufferInfo (h, &sb))
  241. {
  242. cr = sb.dwCursorPosition;
  243. cr.X = 0;
  244. /* Stop at the bottommost boundary. */
  245. if (sb.dwSize.Y - cr.Y > n1)
  246. cr.Y += n1;
  247. else
  248. cr.Y = sb.dwSize.Y;
  249. SetConsoleCursorPosition (h, cr);
  250. }
  251. break;
  252. /* ESC [ n1 'F'
  253. Move the cursor to the beginning of the n1-th line upwards. */
  254. case MAKEWORD ('[', 'F'):
  255. if (esc_head == esc_term)
  256. n1 = 1;
  257. else
  258. {
  259. n1 = strtol (esc_head, &eptr, 10);
  260. if (eptr != esc_term)
  261. break;
  262. }
  263. if (GetConsoleScreenBufferInfo (h, &sb))
  264. {
  265. cr = sb.dwCursorPosition;
  266. cr.X = 0;
  267. /* Stop at the topmost boundary. */
  268. if (cr.Y > n1)
  269. cr.Y -= n1;
  270. else
  271. cr.Y = 0;
  272. SetConsoleCursorPosition (h, cr);
  273. }
  274. break;
  275. /* ESC [ n1 'G'
  276. Move the cursor to the (1-based) n1-th column. */
  277. case MAKEWORD ('[', 'G'):
  278. if (esc_head == esc_term)
  279. n1 = 1;
  280. else
  281. {
  282. n1 = strtol (esc_head, &eptr, 10);
  283. if (eptr != esc_term)
  284. break;
  285. }
  286. if (GetConsoleScreenBufferInfo (h, &sb))
  287. {
  288. cr = sb.dwCursorPosition;
  289. n1 -= 1;
  290. /* Stop at the leftmost or rightmost boundary. */
  291. if (n1 < 0)
  292. cr.X = 0;
  293. else if (n1 > sb.dwSize.X)
  294. cr.X = sb.dwSize.X;
  295. else
  296. cr.X = n1;
  297. SetConsoleCursorPosition (h, cr);
  298. }
  299. break;
  300. /* ESC [ n1 ';' n2 'H'
  301. ESC [ n1 ';' n2 'f'
  302. Move the cursor to the (1-based) n1-th row and
  303. (also 1-based) n2-th column. */
  304. case MAKEWORD ('[', 'H'):
  305. case MAKEWORD ('[', 'f'):
  306. if (esc_head == esc_term)
  307. {
  308. /* Both parameters are omitted and set to 1 by default. */
  309. n1 = 1;
  310. n2 = 1;
  311. }
  312. else if (!(delim = (char *) memchr (esc_head, ';',
  313. esc_term - esc_head)))
  314. {
  315. /* Only the first parameter is given. The second one is
  316. set to 1 by default. */
  317. n1 = strtol (esc_head, &eptr, 10);
  318. if (eptr != esc_term)
  319. break;
  320. n2 = 1;
  321. }
  322. else
  323. {
  324. /* Both parameters are given. The first one shall be
  325. terminated by the semicolon. */
  326. n1 = strtol (esc_head, &eptr, 10);
  327. if (eptr != delim)
  328. break;
  329. n2 = strtol (delim + 1, &eptr, 10);
  330. if (eptr != esc_term)
  331. break;
  332. }
  333. if (GetConsoleScreenBufferInfo (h, &sb))
  334. {
  335. cr = sb.dwCursorPosition;
  336. n1 -= 1;
  337. n2 -= 1;
  338. /* The cursor position shall be relative to the view coord of
  339. the console window, which is usually smaller than the actual
  340. buffer. FWIW, the 'appropriate' solution will be shrinking
  341. the buffer to match the size of the console window,
  342. destroying scrollback in the process. */
  343. n1 += sb.srWindow.Top;
  344. n2 += sb.srWindow.Left;
  345. /* Stop at the topmost or bottommost boundary. */
  346. if (n1 < 0)
  347. cr.Y = 0;
  348. else if (n1 > sb.dwSize.Y)
  349. cr.Y = sb.dwSize.Y;
  350. else
  351. cr.Y = n1;
  352. /* Stop at the leftmost or rightmost boundary. */
  353. if (n2 < 0)
  354. cr.X = 0;
  355. else if (n2 > sb.dwSize.X)
  356. cr.X = sb.dwSize.X;
  357. else
  358. cr.X = n2;
  359. SetConsoleCursorPosition (h, cr);
  360. }
  361. break;
  362. /* ESC [ n1 'J'
  363. Erase display. */
  364. case MAKEWORD ('[', 'J'):
  365. if (esc_head == esc_term)
  366. /* This is one of the very few codes whose parameters have
  367. a default value of zero. */
  368. n1 = 0;
  369. else
  370. {
  371. n1 = strtol (esc_head, &eptr, 10);
  372. if (eptr != esc_term)
  373. break;
  374. }
  375. if (GetConsoleScreenBufferInfo (h, &sb))
  376. {
  377. /* The cursor is not necessarily in the console window, which
  378. makes the behavior of this code harder to define. */
  379. switch (n1)
  380. {
  381. case 0:
  382. /* If the cursor is in or above the window, erase from
  383. it to the bottom of the window; otherwise, do nothing. */
  384. cr = sb.dwCursorPosition;
  385. cnt = sb.dwSize.X - sb.dwCursorPosition.X;
  386. rows = sb.srWindow.Bottom - sb.dwCursorPosition.Y;
  387. break;
  388. case 1:
  389. /* If the cursor is in or under the window, erase from
  390. it to the top of the window; otherwise, do nothing. */
  391. cr.X = 0;
  392. cr.Y = sb.srWindow.Top;
  393. cnt = sb.dwCursorPosition.X + 1;
  394. rows = sb.dwCursorPosition.Y - sb.srWindow.Top;
  395. break;
  396. case 2:
  397. /* Erase the entire window. */
  398. cr.X = sb.srWindow.Left;
  399. cr.Y = sb.srWindow.Top;
  400. cnt = 0;
  401. rows = sb.srWindow.Bottom - sb.srWindow.Top + 1;
  402. break;
  403. default:
  404. /* Erase the entire buffer. */
  405. cr.X = 0;
  406. cr.Y = 0;
  407. cnt = 0;
  408. rows = sb.dwSize.Y;
  409. break;
  410. }
  411. if (rows < 0)
  412. break;
  413. cnt += rows * sb.dwSize.X;
  414. FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
  415. FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
  416. }
  417. break;
  418. /* ESC [ n1 'K'
  419. Erase line. */
  420. case MAKEWORD ('[', 'K'):
  421. if (esc_head == esc_term)
  422. /* This is one of the very few codes whose parameters have
  423. a default value of zero. */
  424. n1 = 0;
  425. else
  426. {
  427. n1 = strtol (esc_head, &eptr, 10);
  428. if (eptr != esc_term)
  429. break;
  430. }
  431. if (GetConsoleScreenBufferInfo (h, &sb))
  432. {
  433. switch (n1)
  434. {
  435. case 0:
  436. /* Erase from the cursor to the end. */
  437. cr = sb.dwCursorPosition;
  438. cnt = sb.dwSize.X - sb.dwCursorPosition.X;
  439. break;
  440. case 1:
  441. /* Erase from the cursor to the beginning. */
  442. cr = sb.dwCursorPosition;
  443. cr.X = 0;
  444. cnt = sb.dwCursorPosition.X + 1;
  445. break;
  446. default:
  447. /* Erase the entire line. */
  448. cr = sb.dwCursorPosition;
  449. cr.X = 0;
  450. cnt = sb.dwSize.X;
  451. break;
  452. }
  453. FillConsoleOutputCharacterW (h, L' ', cnt, cr, &step);
  454. FillConsoleOutputAttribute (h, sb.wAttributes, cnt, cr, &step);
  455. }
  456. break;
  457. /* ESC [ n1 ';' n2 'm'
  458. Set SGR parameters. Zero or more parameters will follow. */
  459. case MAKEWORD ('[', 'm'):
  460. attrib_add = 0;
  461. attrib_rm = 0;
  462. if (esc_head == esc_term)
  463. {
  464. /* When no parameter is given, reset the console. */
  465. attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
  466. | FOREGROUND_BLUE);
  467. attrib_rm = -1; /* Removes everything. */
  468. goto sgr_set_it;
  469. }
  470. param = esc_head;
  471. do
  472. {
  473. /* Parse a parameter. */
  474. n1 = strtol (param, &eptr, 10);
  475. if (*eptr != ';' && eptr != esc_term)
  476. goto sgr_set_it;
  477. switch (n1)
  478. {
  479. case 0:
  480. /* Reset. */
  481. attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
  482. | FOREGROUND_BLUE);
  483. attrib_rm = -1; /* Removes everything. */
  484. break;
  485. case 1:
  486. /* Bold. */
  487. attrib_add |= FOREGROUND_INTENSITY;
  488. break;
  489. case 4:
  490. /* Underline. */
  491. attrib_add |= COMMON_LVB_UNDERSCORE;
  492. break;
  493. case 5:
  494. /* Blink. */
  495. /* XXX: It is not BLINKING at all! */
  496. attrib_add |= BACKGROUND_INTENSITY;
  497. break;
  498. case 7:
  499. /* Reverse. */
  500. attrib_add |= COMMON_LVB_REVERSE_VIDEO;
  501. break;
  502. case 22:
  503. /* No bold. */
  504. attrib_add &= ~FOREGROUND_INTENSITY;
  505. attrib_rm |= FOREGROUND_INTENSITY;
  506. break;
  507. case 24:
  508. /* No underline. */
  509. attrib_add &= ~COMMON_LVB_UNDERSCORE;
  510. attrib_rm |= COMMON_LVB_UNDERSCORE;
  511. break;
  512. case 25:
  513. /* No blink. */
  514. /* XXX: It is not BLINKING at all! */
  515. attrib_add &= ~BACKGROUND_INTENSITY;
  516. attrib_rm |= BACKGROUND_INTENSITY;
  517. break;
  518. case 27:
  519. /* No reverse. */
  520. attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
  521. attrib_rm |= COMMON_LVB_REVERSE_VIDEO;
  522. break;
  523. case 30:
  524. case 31:
  525. case 32:
  526. case 33:
  527. case 34:
  528. case 35:
  529. case 36:
  530. case 37:
  531. /* Foreground color. */
  532. attrib_add &= ~(FOREGROUND_RED | FOREGROUND_GREEN
  533. | FOREGROUND_BLUE);
  534. n1 -= 30;
  535. if (n1 & 1)
  536. attrib_add |= FOREGROUND_RED;
  537. if (n1 & 2)
  538. attrib_add |= FOREGROUND_GREEN;
  539. if (n1 & 4)
  540. attrib_add |= FOREGROUND_BLUE;
  541. attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN
  542. | FOREGROUND_BLUE);
  543. break;
  544. case 38:
  545. /* Reserved for extended foreground color.
  546. Don't know how to handle parameters remaining.
  547. Bail out. */
  548. goto sgr_set_it;
  549. case 39:
  550. /* Reset foreground color. */
  551. /* Set to grey. */
  552. attrib_add |= (FOREGROUND_RED | FOREGROUND_GREEN
  553. | FOREGROUND_BLUE);
  554. attrib_rm |= (FOREGROUND_RED | FOREGROUND_GREEN
  555. | FOREGROUND_BLUE);
  556. break;
  557. case 40:
  558. case 41:
  559. case 42:
  560. case 43:
  561. case 44:
  562. case 45:
  563. case 46:
  564. case 47:
  565. /* Background color. */
  566. attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN
  567. | BACKGROUND_BLUE);
  568. n1 -= 40;
  569. if (n1 & 1)
  570. attrib_add |= BACKGROUND_RED;
  571. if (n1 & 2)
  572. attrib_add |= BACKGROUND_GREEN;
  573. if (n1 & 4)
  574. attrib_add |= BACKGROUND_BLUE;
  575. attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN
  576. | BACKGROUND_BLUE);
  577. break;
  578. case 48:
  579. /* Reserved for extended background color.
  580. Don't know how to handle parameters remaining.
  581. Bail out. */
  582. goto sgr_set_it;
  583. case 49:
  584. /* Reset background color. */
  585. /* Set to black. */
  586. attrib_add &= ~(BACKGROUND_RED | BACKGROUND_GREEN
  587. | BACKGROUND_BLUE);
  588. attrib_rm |= (BACKGROUND_RED | BACKGROUND_GREEN
  589. | BACKGROUND_BLUE);
  590. break;
  591. }
  592. /* Prepare the next parameter. */
  593. param = eptr + 1;
  594. }
  595. while (param != esc_term);
  596. sgr_set_it:
  597. /* 0xFFFF removes everything. If it is not the case,
  598. care must be taken to preserve old attributes. */
  599. if (attrib_rm != 0xFFFF && GetConsoleScreenBufferInfo (h, &sb))
  600. {
  601. attrib_add |= sb.wAttributes & ~attrib_rm;
  602. }
  603. if (attrib_add & COMMON_LVB_REVERSE_VIDEO)
  604. {
  605. /* COMMON_LVB_REVERSE_VIDEO is only effective for DBCS.
  606. * Swap foreground and background colors by hand.
  607. */
  608. attrib_add = (attrib_add & 0xFF00)
  609. | ((attrib_add & 0x00F0) >> 4)
  610. | ((attrib_add & 0x000F) << 4);
  611. attrib_add &= ~COMMON_LVB_REVERSE_VIDEO;
  612. }
  613. SetConsoleTextAttribute (h, attrib_add);
  614. break;
  615. }
  616. }
  617. int
  618. mingw_ansi_fputs (const char *str, FILE *fp)
  619. {
  620. const char *read = str;
  621. HANDLE h;
  622. DWORD mode;
  623. int esc_code, prefix_len;
  624. const char *esc_head, *esc_term;
  625. h = (HANDLE) _get_osfhandle (_fileno (fp));
  626. if (h == INVALID_HANDLE_VALUE)
  627. return EOF;
  628. /* Don't mess up stdio functions with Windows APIs. */
  629. fflush (fp);
  630. if (GetConsoleMode (h, &mode))
  631. /* If it is a console, translate ANSI escape codes as needed. */
  632. for (;;)
  633. {
  634. if ((esc_code = find_esc_head (&prefix_len, &esc_head, read)) == 0)
  635. {
  636. /* Write all remaining characters, then exit. */
  637. write_all (h, read, strlen (read));
  638. break;
  639. }
  640. if (find_esc_terminator (&esc_term, esc_head) == 0)
  641. /* Ignore incomplete escape sequences at the moment.
  642. FIXME: The escape state shall be cached for further calls
  643. to this function. */
  644. break;
  645. write_all (h, read, esc_head - prefix_len - read);
  646. eat_esc_sequence (h, esc_code, esc_head, esc_term);
  647. read = esc_term + 1;
  648. }
  649. else
  650. /* If it is not a console, write everything as-is. */
  651. write_all (h, read, strlen (read));
  652. return 1;
  653. }
  654. #endif /* __MINGW32__ */
  655. static int
  656. decode_utf8_char (const unsigned char *, size_t len, unsigned int *);
  657. static void pp_quoted_string (pretty_printer *, const char *, size_t = -1);
  658. /* Overwrite the given location/range within this text_info's rich_location.
  659. For use e.g. when implementing "+" in client format decoders. */
  660. void
  661. text_info::set_location (unsigned int idx, location_t loc,
  662. enum range_display_kind range_display_kind)
  663. {
  664. gcc_checking_assert (m_richloc);
  665. m_richloc->set_range (idx, loc, range_display_kind);
  666. }
  667. location_t
  668. text_info::get_location (unsigned int index_of_location) const
  669. {
  670. gcc_checking_assert (m_richloc);
  671. if (index_of_location == 0)
  672. return m_richloc->get_loc ();
  673. else
  674. return UNKNOWN_LOCATION;
  675. }
  676. // Default construct an output buffer.
  677. output_buffer::output_buffer ()
  678. : formatted_obstack (),
  679. chunk_obstack (),
  680. obstack (&formatted_obstack),
  681. cur_chunk_array (),
  682. stream (stderr),
  683. line_length (),
  684. digit_buffer (),
  685. flush_p (true)
  686. {
  687. obstack_init (&formatted_obstack);
  688. obstack_init (&chunk_obstack);
  689. }
  690. // Release resources owned by an output buffer at the end of lifetime.
  691. output_buffer::~output_buffer ()
  692. {
  693. obstack_free (&chunk_obstack, NULL);
  694. obstack_free (&formatted_obstack, NULL);
  695. }
  696. /* Format an integer given by va_arg (ARG, type-specifier T) where
  697. type-specifier is a precision modifier as indicated by PREC. F is
  698. a string used to construct the appropriate format-specifier. */
  699. #define pp_integer_with_precision(PP, ARG, PREC, T, F) \
  700. do \
  701. switch (PREC) \
  702. { \
  703. case 0: \
  704. pp_scalar (PP, "%" F, va_arg (ARG, T)); \
  705. break; \
  706. \
  707. case 1: \
  708. pp_scalar (PP, "%l" F, va_arg (ARG, long T)); \
  709. break; \
  710. \
  711. case 2: \
  712. pp_scalar (PP, "%" HOST_LONG_LONG_FORMAT F, va_arg (ARG, long long T)); \
  713. break; \
  714. \
  715. default: \
  716. break; \
  717. } \
  718. while (0)
  719. /* Subroutine of pp_set_maximum_length. Set up PRETTY-PRINTER's
  720. internal maximum characters per line. */
  721. static void
  722. pp_set_real_maximum_length (pretty_printer *pp)
  723. {
  724. /* If we're told not to wrap lines then do the obvious thing. In case
  725. we'll emit prefix only once per message, it is appropriate
  726. not to increase unnecessarily the line-length cut-off. */
  727. if (!pp_is_wrapping_line (pp)
  728. || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_ONCE
  729. || pp_prefixing_rule (pp) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
  730. pp->maximum_length = pp_line_cutoff (pp);
  731. else
  732. {
  733. int prefix_length = pp->prefix ? strlen (pp->prefix) : 0;
  734. /* If the prefix is ridiculously too long, output at least
  735. 32 characters. */
  736. if (pp_line_cutoff (pp) - prefix_length < 32)
  737. pp->maximum_length = pp_line_cutoff (pp) + 32;
  738. else
  739. pp->maximum_length = pp_line_cutoff (pp);
  740. }
  741. }
  742. /* Clear PRETTY-PRINTER's output state. */
  743. static inline void
  744. pp_clear_state (pretty_printer *pp)
  745. {
  746. pp->emitted_prefix = false;
  747. pp_indentation (pp) = 0;
  748. }
  749. /* Print X to PP in decimal. */
  750. template<unsigned int N, typename T>
  751. void
  752. pp_wide_integer (pretty_printer *pp, const poly_int_pod<N, T> &x)
  753. {
  754. if (x.is_constant ())
  755. pp_wide_integer (pp, x.coeffs[0]);
  756. else
  757. {
  758. pp_left_bracket (pp);
  759. for (unsigned int i = 0; i < N; ++i)
  760. {
  761. if (i != 0)
  762. pp_comma (pp);
  763. pp_wide_integer (pp, x.coeffs[i]);
  764. }
  765. pp_right_bracket (pp);
  766. }
  767. }
  768. template void pp_wide_integer (pretty_printer *, const poly_uint16_pod &);
  769. template void pp_wide_integer (pretty_printer *, const poly_int64_pod &);
  770. template void pp_wide_integer (pretty_printer *, const poly_uint64_pod &);
  771. /* Flush the formatted text of PRETTY-PRINTER onto the attached stream. */
  772. void
  773. pp_write_text_to_stream (pretty_printer *pp)
  774. {
  775. const char *text = pp_formatted_text (pp);
  776. #ifdef __MINGW32__
  777. mingw_ansi_fputs (text, pp_buffer (pp)->stream);
  778. #else
  779. fputs (text, pp_buffer (pp)->stream);
  780. #endif
  781. pp_clear_output_area (pp);
  782. }
  783. /* As pp_write_text_to_stream, but for GraphViz label output.
  784. Flush the formatted text of pretty-printer PP onto the attached stream.
  785. Replace characters in PPF that have special meaning in a GraphViz .dot
  786. file.
  787. This routine is not very fast, but it doesn't have to be as this is only
  788. be used by routines dumping intermediate representations in graph form. */
  789. void
  790. pp_write_text_as_dot_label_to_stream (pretty_printer *pp, bool for_record)
  791. {
  792. const char *text = pp_formatted_text (pp);
  793. const char *p = text;
  794. FILE *fp = pp_buffer (pp)->stream;
  795. for (;*p; p++)
  796. {
  797. bool escape_char;
  798. switch (*p)
  799. {
  800. /* Print newlines as a left-aligned newline. */
  801. case '\n':
  802. fputs ("\\l", fp);
  803. escape_char = true;
  804. break;
  805. /* The following characters are only special for record-shape nodes. */
  806. case '|':
  807. case '{':
  808. case '}':
  809. case '<':
  810. case '>':
  811. case ' ':
  812. escape_char = for_record;
  813. break;
  814. /* The following characters always have to be escaped
  815. for use in labels. */
  816. case '\\':
  817. /* There is a bug in some (f.i. 2.36.0) versions of graphiz
  818. ( http://www.graphviz.org/mantisbt/view.php?id=2524 ) related to
  819. backslash as last char in label. Let's avoid triggering it. */
  820. gcc_assert (*(p + 1) != '\0');
  821. /* Fall through. */
  822. case '"':
  823. escape_char = true;
  824. break;
  825. default:
  826. escape_char = false;
  827. break;
  828. }
  829. if (escape_char)
  830. fputc ('\\', fp);
  831. fputc (*p, fp);
  832. }
  833. pp_clear_output_area (pp);
  834. }
  835. /* As pp_write_text_to_stream, but for GraphViz HTML-like strings.
  836. Flush the formatted text of pretty-printer PP onto the attached stream,
  837. escaping these characters
  838. " & < >
  839. using XML escape sequences.
  840. http://www.graphviz.org/doc/info/lang.html#html states:
  841. special XML escape sequences for ", &, <, and > may be necessary in
  842. order to embed these characters in attribute values or raw text
  843. This doesn't list "'" (which would normally be escaped in XML
  844. as "&apos;" or in HTML as "&#39;");.
  845. Experiments show that escaping "'" doesn't seem to be necessary. */
  846. void
  847. pp_write_text_as_html_like_dot_to_stream (pretty_printer *pp)
  848. {
  849. const char *text = pp_formatted_text (pp);
  850. const char *p = text;
  851. FILE *fp = pp_buffer (pp)->stream;
  852. for (;*p; p++)
  853. {
  854. switch (*p)
  855. {
  856. case '"':
  857. fputs ("&quot;", fp);
  858. break;
  859. case '&':
  860. fputs ("&amp;", fp);
  861. break;
  862. case '<':
  863. fputs ("&lt;", fp);
  864. break;
  865. case '>':
  866. fputs ("&gt;",fp);
  867. break;
  868. default:
  869. fputc (*p, fp);
  870. break;
  871. }
  872. }
  873. pp_clear_output_area (pp);
  874. }
  875. /* Wrap a text delimited by START and END into PRETTY-PRINTER. */
  876. static void
  877. pp_wrap_text (pretty_printer *pp, const char *start, const char *end)
  878. {
  879. bool wrapping_line = pp_is_wrapping_line (pp);
  880. while (start != end)
  881. {
  882. /* Dump anything bordered by whitespaces. */
  883. {
  884. const char *p = start;
  885. while (p != end && !ISBLANK (*p) && *p != '\n')
  886. ++p;
  887. if (wrapping_line
  888. && p - start >= pp_remaining_character_count_for_line (pp))
  889. pp_newline (pp);
  890. pp_append_text (pp, start, p);
  891. start = p;
  892. }
  893. if (start != end && ISBLANK (*start))
  894. {
  895. pp_space (pp);
  896. ++start;
  897. }
  898. if (start != end && *start == '\n')
  899. {
  900. pp_newline (pp);
  901. ++start;
  902. }
  903. }
  904. }
  905. /* Same as pp_wrap_text but wrap text only when in line-wrapping mode. */
  906. static inline void
  907. pp_maybe_wrap_text (pretty_printer *pp, const char *start, const char *end)
  908. {
  909. if (pp_is_wrapping_line (pp))
  910. pp_wrap_text (pp, start, end);
  911. else
  912. pp_append_text (pp, start, end);
  913. }
  914. /* Append to the output area of PRETTY-PRINTER a string specified by its
  915. STARTing character and LENGTH. */
  916. static inline void
  917. pp_append_r (pretty_printer *pp, const char *start, int length)
  918. {
  919. output_buffer_append_r (pp_buffer (pp), start, length);
  920. }
  921. /* Insert enough spaces into the output area of PRETTY-PRINTER to bring
  922. the column position to the current indentation level, assuming that a
  923. newline has just been written to the buffer. */
  924. void
  925. pp_indent (pretty_printer *pp)
  926. {
  927. int n = pp_indentation (pp);
  928. int i;
  929. for (i = 0; i < n; ++i)
  930. pp_space (pp);
  931. }
  932. static const char *get_end_url_string (pretty_printer *);
  933. /* The following format specifiers are recognized as being client independent:
  934. %d, %i: (signed) integer in base ten.
  935. %u: unsigned integer in base ten.
  936. %o: unsigned integer in base eight.
  937. %x: unsigned integer in base sixteen.
  938. %ld, %li, %lo, %lu, %lx: long versions of the above.
  939. %lld, %lli, %llo, %llu, %llx: long long versions.
  940. %wd, %wi, %wo, %wu, %wx: HOST_WIDE_INT versions.
  941. %f: double
  942. %c: character.
  943. %s: string.
  944. %p: pointer (printed in a host-dependent manner).
  945. %r: if pp_show_color(pp), switch to color identified by const char *.
  946. %R: if pp_show_color(pp), reset color.
  947. %m: strerror(text->err_no) - does not consume a value from args_ptr.
  948. %%: '%'.
  949. %<: opening quote.
  950. %>: closing quote.
  951. %{: URL start. Consumes a const char * argument for the URL.
  952. %}: URL end. Does not consume any arguments.
  953. %': apostrophe (should only be used in untranslated messages;
  954. translations should use appropriate punctuation directly).
  955. %@: diagnostic_event_id_ptr, for which event_id->known_p () must be true.
  956. %.*s: a substring the length of which is specified by an argument
  957. integer.
  958. %Ns: likewise, but length specified as constant in the format string.
  959. Flag 'q': quote formatted text (must come immediately after '%').
  960. %Z: Requires two arguments - array of int, and len. Prints elements
  961. of the array.
  962. Arguments can be used sequentially, or through %N$ resp. *N$
  963. notation Nth argument after the format string. If %N$ / *N$
  964. notation is used, it must be used for all arguments, except %m, %%,
  965. %<, %>, %} and %', which may not have a number, as they do not consume
  966. an argument. When %M$.*N$s is used, M must be N + 1. (This may
  967. also be written %M$.*s, provided N is not otherwise used.) The
  968. format string must have conversion specifiers with argument numbers
  969. 1 up to highest argument; each argument may only be used once.
  970. A format string can have at most 30 arguments. */
  971. /* Formatting phases 1 and 2: render TEXT->format_spec plus
  972. TEXT->args_ptr into a series of chunks in pp_buffer (PP)->args[].
  973. Phase 3 is in pp_output_formatted_text. */
  974. void
  975. pp_format (pretty_printer *pp, text_info *text)
  976. {
  977. output_buffer *buffer = pp_buffer (pp);
  978. const char *p;
  979. const char **args;
  980. struct chunk_info *new_chunk_array;
  981. unsigned int curarg = 0, chunk = 0, argno;
  982. pp_wrapping_mode_t old_wrapping_mode;
  983. bool any_unnumbered = false, any_numbered = false;
  984. const char **formatters[PP_NL_ARGMAX];
  985. /* Allocate a new chunk structure. */
  986. new_chunk_array = XOBNEW (&buffer->chunk_obstack, struct chunk_info);
  987. new_chunk_array->prev = buffer->cur_chunk_array;
  988. buffer->cur_chunk_array = new_chunk_array;
  989. args = new_chunk_array->args;
  990. /* Formatting phase 1: split up TEXT->format_spec into chunks in
  991. pp_buffer (PP)->args[]. Even-numbered chunks are to be output
  992. verbatim, odd-numbered chunks are format specifiers.
  993. %m, %%, %<, %>, %} and %' are replaced with the appropriate text at
  994. this point. */
  995. memset (formatters, 0, sizeof formatters);
  996. for (p = text->format_spec; *p; )
  997. {
  998. while (*p != '\0' && *p != '%')
  999. {
  1000. obstack_1grow (&buffer->chunk_obstack, *p);
  1001. p++;
  1002. }
  1003. if (*p == '\0')
  1004. break;
  1005. switch (*++p)
  1006. {
  1007. case '\0':
  1008. gcc_unreachable ();
  1009. case '%':
  1010. obstack_1grow (&buffer->chunk_obstack, '%');
  1011. p++;
  1012. continue;
  1013. case '<':
  1014. {
  1015. obstack_grow (&buffer->chunk_obstack,
  1016. open_quote, strlen (open_quote));
  1017. const char *colorstr
  1018. = colorize_start (pp_show_color (pp), "quote");
  1019. obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
  1020. p++;
  1021. continue;
  1022. }
  1023. case '>':
  1024. {
  1025. const char *colorstr = colorize_stop (pp_show_color (pp));
  1026. obstack_grow (&buffer->chunk_obstack, colorstr, strlen (colorstr));
  1027. }
  1028. /* FALLTHRU */
  1029. case '\'':
  1030. obstack_grow (&buffer->chunk_obstack,
  1031. close_quote, strlen (close_quote));
  1032. p++;
  1033. continue;
  1034. case '}':
  1035. {
  1036. const char *endurlstr = get_end_url_string (pp);
  1037. obstack_grow (&buffer->chunk_obstack, endurlstr,
  1038. strlen (endurlstr));
  1039. }
  1040. p++;
  1041. continue;
  1042. case 'R':
  1043. {
  1044. const char *colorstr = colorize_stop (pp_show_color (pp));
  1045. obstack_grow (&buffer->chunk_obstack, colorstr,
  1046. strlen (colorstr));
  1047. p++;
  1048. continue;
  1049. }
  1050. case 'm':
  1051. {
  1052. const char *errstr = xstrerror (text->err_no);
  1053. obstack_grow (&buffer->chunk_obstack, errstr, strlen (errstr));
  1054. }
  1055. p++;
  1056. continue;
  1057. default:
  1058. /* Handled in phase 2. Terminate the plain chunk here. */
  1059. obstack_1grow (&buffer->chunk_obstack, '\0');
  1060. gcc_assert (chunk < PP_NL_ARGMAX * 2);
  1061. args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
  1062. break;
  1063. }
  1064. if (ISDIGIT (*p))
  1065. {
  1066. char *end;
  1067. argno = strtoul (p, &end, 10) - 1;
  1068. p = end;
  1069. gcc_assert (*p == '$');
  1070. p++;
  1071. any_numbered = true;
  1072. gcc_assert (!any_unnumbered);
  1073. }
  1074. else
  1075. {
  1076. argno = curarg++;
  1077. any_unnumbered = true;
  1078. gcc_assert (!any_numbered);
  1079. }
  1080. gcc_assert (argno < PP_NL_ARGMAX);
  1081. gcc_assert (!formatters[argno]);
  1082. formatters[argno] = &args[chunk];
  1083. do
  1084. {
  1085. obstack_1grow (&buffer->chunk_obstack, *p);
  1086. p++;
  1087. }
  1088. while (strchr ("qwl+#", p[-1]));
  1089. if (p[-1] == '.')
  1090. {
  1091. /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
  1092. (where M == N + 1). */
  1093. if (ISDIGIT (*p))
  1094. {
  1095. do
  1096. {
  1097. obstack_1grow (&buffer->chunk_obstack, *p);
  1098. p++;
  1099. }
  1100. while (ISDIGIT (p[-1]));
  1101. gcc_assert (p[-1] == 's');
  1102. }
  1103. else
  1104. {
  1105. gcc_assert (*p == '*');
  1106. obstack_1grow (&buffer->chunk_obstack, '*');
  1107. p++;
  1108. if (ISDIGIT (*p))
  1109. {
  1110. char *end;
  1111. unsigned int argno2 = strtoul (p, &end, 10) - 1;
  1112. p = end;
  1113. gcc_assert (argno2 == argno - 1);
  1114. gcc_assert (!any_unnumbered);
  1115. gcc_assert (*p == '$');
  1116. p++;
  1117. formatters[argno2] = formatters[argno];
  1118. }
  1119. else
  1120. {
  1121. gcc_assert (!any_numbered);
  1122. formatters[argno+1] = formatters[argno];
  1123. curarg++;
  1124. }
  1125. gcc_assert (*p == 's');
  1126. obstack_1grow (&buffer->chunk_obstack, 's');
  1127. p++;
  1128. }
  1129. }
  1130. if (*p == '\0')
  1131. break;
  1132. obstack_1grow (&buffer->chunk_obstack, '\0');
  1133. gcc_assert (chunk < PP_NL_ARGMAX * 2);
  1134. args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
  1135. }
  1136. obstack_1grow (&buffer->chunk_obstack, '\0');
  1137. gcc_assert (chunk < PP_NL_ARGMAX * 2);
  1138. args[chunk++] = XOBFINISH (&buffer->chunk_obstack, const char *);
  1139. args[chunk] = 0;
  1140. /* Set output to the argument obstack, and switch line-wrapping and
  1141. prefixing off. */
  1142. buffer->obstack = &buffer->chunk_obstack;
  1143. const int old_line_length = buffer->line_length;
  1144. old_wrapping_mode = pp_set_verbatim_wrapping (pp);
  1145. /* Second phase. Replace each formatter with the formatted text it
  1146. corresponds to. */
  1147. for (argno = 0; formatters[argno]; argno++)
  1148. {
  1149. int precision = 0;
  1150. bool wide = false;
  1151. bool plus = false;
  1152. bool hash = false;
  1153. bool quote = false;
  1154. /* We do not attempt to enforce any ordering on the modifier
  1155. characters. */
  1156. for (p = *formatters[argno];; p++)
  1157. {
  1158. switch (*p)
  1159. {
  1160. case 'q':
  1161. gcc_assert (!quote);
  1162. quote = true;
  1163. continue;
  1164. case '+':
  1165. gcc_assert (!plus);
  1166. plus = true;
  1167. continue;
  1168. case '#':
  1169. gcc_assert (!hash);
  1170. hash = true;
  1171. continue;
  1172. case 'w':
  1173. gcc_assert (!wide);
  1174. wide = true;
  1175. continue;
  1176. case 'l':
  1177. /* We don't support precision beyond that of "long long". */
  1178. gcc_assert (precision < 2);
  1179. precision++;
  1180. continue;
  1181. }
  1182. break;
  1183. }
  1184. gcc_assert (!wide || precision == 0);
  1185. if (quote)
  1186. pp_begin_quote (pp, pp_show_color (pp));
  1187. switch (*p)
  1188. {
  1189. case 'r':
  1190. pp_string (pp, colorize_start (pp_show_color (pp),
  1191. va_arg (*text->args_ptr,
  1192. const char *)));
  1193. break;
  1194. case 'c':
  1195. {
  1196. /* When quoting, print alphanumeric, punctuation, and the space
  1197. character unchanged, and all others in hexadecimal with the
  1198. "\x" prefix. Otherwise print them all unchanged. */
  1199. int chr = va_arg (*text->args_ptr, int);
  1200. if (ISPRINT (chr) || !quote)
  1201. pp_character (pp, chr);
  1202. else
  1203. {
  1204. const char str [2] = { chr, '\0' };
  1205. pp_quoted_string (pp, str, 1);
  1206. }
  1207. break;
  1208. }
  1209. case 'd':
  1210. case 'i':
  1211. if (wide)
  1212. pp_wide_integer (pp, va_arg (*text->args_ptr, HOST_WIDE_INT));
  1213. else
  1214. pp_integer_with_precision
  1215. (pp, *text->args_ptr, precision, int, "d");
  1216. break;
  1217. case 'o':
  1218. if (wide)
  1219. pp_scalar (pp, "%" HOST_WIDE_INT_PRINT "o",
  1220. va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
  1221. else
  1222. pp_integer_with_precision
  1223. (pp, *text->args_ptr, precision, unsigned, "o");
  1224. break;
  1225. case 's':
  1226. if (quote)
  1227. pp_quoted_string (pp, va_arg (*text->args_ptr, const char *));
  1228. else
  1229. pp_string (pp, va_arg (*text->args_ptr, const char *));
  1230. break;
  1231. case 'p':
  1232. pp_pointer (pp, va_arg (*text->args_ptr, void *));
  1233. break;
  1234. case 'u':
  1235. if (wide)
  1236. pp_scalar (pp, HOST_WIDE_INT_PRINT_UNSIGNED,
  1237. va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
  1238. else
  1239. pp_integer_with_precision
  1240. (pp, *text->args_ptr, precision, unsigned, "u");
  1241. break;
  1242. case 'f':
  1243. pp_double (pp, va_arg (*text->args_ptr, double));
  1244. break;
  1245. case 'Z':
  1246. {
  1247. int *v = va_arg (*text->args_ptr, int *);
  1248. unsigned len = va_arg (*text->args_ptr, unsigned);
  1249. for (unsigned i = 0; i < len; ++i)
  1250. {
  1251. pp_scalar (pp, "%i", v[i]);
  1252. if (i < len - 1)
  1253. {
  1254. pp_comma (pp);
  1255. pp_space (pp);
  1256. }
  1257. }
  1258. break;
  1259. }
  1260. case 'x':
  1261. if (wide)
  1262. pp_scalar (pp, HOST_WIDE_INT_PRINT_HEX,
  1263. va_arg (*text->args_ptr, unsigned HOST_WIDE_INT));
  1264. else
  1265. pp_integer_with_precision
  1266. (pp, *text->args_ptr, precision, unsigned, "x");
  1267. break;
  1268. case '.':
  1269. {
  1270. int n;
  1271. const char *s;
  1272. /* We handle '%.Ns' and '%.*s' or '%M$.*N$s'
  1273. (where M == N + 1). The format string should be verified
  1274. already from the first phase. */
  1275. p++;
  1276. if (ISDIGIT (*p))
  1277. {
  1278. char *end;
  1279. n = strtoul (p, &end, 10);
  1280. p = end;
  1281. gcc_assert (*p == 's');
  1282. }
  1283. else
  1284. {
  1285. gcc_assert (*p == '*');
  1286. p++;
  1287. gcc_assert (*p == 's');
  1288. n = va_arg (*text->args_ptr, int);
  1289. /* This consumes a second entry in the formatters array. */
  1290. gcc_assert (formatters[argno] == formatters[argno+1]);
  1291. argno++;
  1292. }
  1293. s = va_arg (*text->args_ptr, const char *);
  1294. /* Append the lesser of precision and strlen (s) characters
  1295. from the array (which need not be a nul-terminated string).
  1296. Negative precision is treated as if it were omitted. */
  1297. size_t len = n < 0 ? strlen (s) : strnlen (s, n);
  1298. pp_append_text (pp, s, s + len);
  1299. }
  1300. break;
  1301. case '@':
  1302. {
  1303. /* diagnostic_event_id_t *. */
  1304. diagnostic_event_id_ptr event_id
  1305. = va_arg (*text->args_ptr, diagnostic_event_id_ptr);
  1306. gcc_assert (event_id->known_p ());
  1307. pp_string (pp, colorize_start (pp_show_color (pp), "path"));
  1308. pp_character (pp, '(');
  1309. pp_decimal_int (pp, event_id->one_based ());
  1310. pp_character (pp, ')');
  1311. pp_string (pp, colorize_stop (pp_show_color (pp)));
  1312. }
  1313. break;
  1314. case '{':
  1315. pp_begin_url (pp, va_arg (*text->args_ptr, const char *));
  1316. break;
  1317. default:
  1318. {
  1319. bool ok;
  1320. /* Call the format decoder.
  1321. Pass the address of "quote" so that format decoders can
  1322. potentially disable printing of the closing quote
  1323. (e.g. when printing "'TYPEDEF' aka 'TYPE'" in the C family
  1324. of frontends). */
  1325. gcc_assert (pp_format_decoder (pp));
  1326. ok = pp_format_decoder (pp) (pp, text, p,
  1327. precision, wide, plus, hash, &quote,
  1328. formatters[argno]);
  1329. gcc_assert (ok);
  1330. }
  1331. }
  1332. if (quote)
  1333. pp_end_quote (pp, pp_show_color (pp));
  1334. obstack_1grow (&buffer->chunk_obstack, '\0');
  1335. *formatters[argno] = XOBFINISH (&buffer->chunk_obstack, const char *);
  1336. }
  1337. if (CHECKING_P)
  1338. for (; argno < PP_NL_ARGMAX; argno++)
  1339. gcc_assert (!formatters[argno]);
  1340. /* If the client supplied a postprocessing object, call its "handle"
  1341. hook here. */
  1342. if (pp->m_format_postprocessor)
  1343. pp->m_format_postprocessor->handle (pp);
  1344. /* Revert to normal obstack and wrapping mode. */
  1345. buffer->obstack = &buffer->formatted_obstack;
  1346. buffer->line_length = old_line_length;
  1347. pp_wrapping_mode (pp) = old_wrapping_mode;
  1348. pp_clear_state (pp);
  1349. }
  1350. /* Format of a message pointed to by TEXT. */
  1351. void
  1352. pp_output_formatted_text (pretty_printer *pp)
  1353. {
  1354. unsigned int chunk;
  1355. output_buffer *buffer = pp_buffer (pp);
  1356. struct chunk_info *chunk_array = buffer->cur_chunk_array;
  1357. const char **args = chunk_array->args;
  1358. gcc_assert (buffer->obstack == &buffer->formatted_obstack);
  1359. /* This is a third phase, first 2 phases done in pp_format_args.
  1360. Now we actually print it. */
  1361. for (chunk = 0; args[chunk]; chunk++)
  1362. pp_string (pp, args[chunk]);
  1363. /* Deallocate the chunk structure and everything after it (i.e. the
  1364. associated series of formatted strings). */
  1365. buffer->cur_chunk_array = chunk_array->prev;
  1366. obstack_free (&buffer->chunk_obstack, chunk_array);
  1367. }
  1368. /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
  1369. settings needed by BUFFER for a verbatim formatting. */
  1370. void
  1371. pp_format_verbatim (pretty_printer *pp, text_info *text)
  1372. {
  1373. /* Set verbatim mode. */
  1374. pp_wrapping_mode_t oldmode = pp_set_verbatim_wrapping (pp);
  1375. /* Do the actual formatting. */
  1376. pp_format (pp, text);
  1377. pp_output_formatted_text (pp);
  1378. /* Restore previous settings. */
  1379. pp_wrapping_mode (pp) = oldmode;
  1380. }
  1381. /* Flush the content of BUFFER onto the attached stream. This
  1382. function does nothing unless pp->output_buffer->flush_p. */
  1383. void
  1384. pp_flush (pretty_printer *pp)
  1385. {
  1386. pp_clear_state (pp);
  1387. if (!pp->buffer->flush_p)
  1388. return;
  1389. pp_write_text_to_stream (pp);
  1390. fflush (pp_buffer (pp)->stream);
  1391. }
  1392. /* Flush the content of BUFFER onto the attached stream independently
  1393. of the value of pp->output_buffer->flush_p. */
  1394. void
  1395. pp_really_flush (pretty_printer *pp)
  1396. {
  1397. pp_clear_state (pp);
  1398. pp_write_text_to_stream (pp);
  1399. fflush (pp_buffer (pp)->stream);
  1400. }
  1401. /* Sets the number of maximum characters per line PRETTY-PRINTER can
  1402. output in line-wrapping mode. A LENGTH value 0 suppresses
  1403. line-wrapping. */
  1404. void
  1405. pp_set_line_maximum_length (pretty_printer *pp, int length)
  1406. {
  1407. pp_line_cutoff (pp) = length;
  1408. pp_set_real_maximum_length (pp);
  1409. }
  1410. /* Clear PRETTY-PRINTER output area text info. */
  1411. void
  1412. pp_clear_output_area (pretty_printer *pp)
  1413. {
  1414. obstack_free (pp_buffer (pp)->obstack,
  1415. obstack_base (pp_buffer (pp)->obstack));
  1416. pp_buffer (pp)->line_length = 0;
  1417. }
  1418. /* Set PREFIX for PRETTY-PRINTER, taking ownership of PREFIX, which
  1419. will eventually be free-ed. */
  1420. void
  1421. pp_set_prefix (pretty_printer *pp, char *prefix)
  1422. {
  1423. free (pp->prefix);
  1424. pp->prefix = prefix;
  1425. pp_set_real_maximum_length (pp);
  1426. pp->emitted_prefix = false;
  1427. pp_indentation (pp) = 0;
  1428. }
  1429. /* Take ownership of PP's prefix, setting it to NULL.
  1430. This allows clients to save, override, and then restore an existing
  1431. prefix, without it being free-ed. */
  1432. char *
  1433. pp_take_prefix (pretty_printer *pp)
  1434. {
  1435. char *result = pp->prefix;
  1436. pp->prefix = NULL;
  1437. return result;
  1438. }
  1439. /* Free PRETTY-PRINTER's prefix, a previously malloc()'d string. */
  1440. void
  1441. pp_destroy_prefix (pretty_printer *pp)
  1442. {
  1443. if (pp->prefix != NULL)
  1444. {
  1445. free (pp->prefix);
  1446. pp->prefix = NULL;
  1447. }
  1448. }
  1449. /* Write out PRETTY-PRINTER's prefix. */
  1450. void
  1451. pp_emit_prefix (pretty_printer *pp)
  1452. {
  1453. if (pp->prefix != NULL)
  1454. {
  1455. switch (pp_prefixing_rule (pp))
  1456. {
  1457. default:
  1458. case DIAGNOSTICS_SHOW_PREFIX_NEVER:
  1459. break;
  1460. case DIAGNOSTICS_SHOW_PREFIX_ONCE:
  1461. if (pp->emitted_prefix)
  1462. {
  1463. pp_indent (pp);
  1464. break;
  1465. }
  1466. pp_indentation (pp) += 3;
  1467. /* Fall through. */
  1468. case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
  1469. {
  1470. int prefix_length = strlen (pp->prefix);
  1471. pp_append_r (pp, pp->prefix, prefix_length);
  1472. pp->emitted_prefix = true;
  1473. }
  1474. break;
  1475. }
  1476. }
  1477. }
  1478. /* Construct a PRETTY-PRINTER of MAXIMUM_LENGTH characters per line. */
  1479. pretty_printer::pretty_printer (int maximum_length)
  1480. : buffer (new (XCNEW (output_buffer)) output_buffer ()),
  1481. prefix (),
  1482. padding (pp_none),
  1483. maximum_length (),
  1484. indent_skip (),
  1485. wrapping (),
  1486. format_decoder (),
  1487. m_format_postprocessor (NULL),
  1488. emitted_prefix (),
  1489. need_newline (),
  1490. translate_identifiers (true),
  1491. show_color (),
  1492. url_format (URL_FORMAT_NONE)
  1493. {
  1494. pp_line_cutoff (this) = maximum_length;
  1495. /* By default, we emit prefixes once per message. */
  1496. pp_prefixing_rule (this) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
  1497. pp_set_prefix (this, NULL);
  1498. }
  1499. /* Copy constructor for pretty_printer. */
  1500. pretty_printer::pretty_printer (const pretty_printer &other)
  1501. : buffer (new (XCNEW (output_buffer)) output_buffer ()),
  1502. prefix (),
  1503. padding (other.padding),
  1504. maximum_length (other.maximum_length),
  1505. indent_skip (other.indent_skip),
  1506. wrapping (other.wrapping),
  1507. format_decoder (other.format_decoder),
  1508. m_format_postprocessor (NULL),
  1509. emitted_prefix (other.emitted_prefix),
  1510. need_newline (other.need_newline),
  1511. translate_identifiers (other.translate_identifiers),
  1512. show_color (other.show_color),
  1513. url_format (other.url_format)
  1514. {
  1515. pp_line_cutoff (this) = maximum_length;
  1516. /* By default, we emit prefixes once per message. */
  1517. pp_prefixing_rule (this) = pp_prefixing_rule (&other);
  1518. pp_set_prefix (this, NULL);
  1519. if (other.m_format_postprocessor)
  1520. m_format_postprocessor = other.m_format_postprocessor->clone ();
  1521. }
  1522. pretty_printer::~pretty_printer ()
  1523. {
  1524. if (m_format_postprocessor)
  1525. delete m_format_postprocessor;
  1526. buffer->~output_buffer ();
  1527. XDELETE (buffer);
  1528. free (prefix);
  1529. }
  1530. /* Base class implementation of pretty_printer::clone vfunc. */
  1531. pretty_printer *
  1532. pretty_printer::clone () const
  1533. {
  1534. return new pretty_printer (*this);
  1535. }
  1536. /* Append a string delimited by START and END to the output area of
  1537. PRETTY-PRINTER. No line wrapping is done. However, if beginning a
  1538. new line then emit PRETTY-PRINTER's prefix and skip any leading
  1539. whitespace if appropriate. The caller must ensure that it is
  1540. safe to do so. */
  1541. void
  1542. pp_append_text (pretty_printer *pp, const char *start, const char *end)
  1543. {
  1544. /* Emit prefix and skip whitespace if we're starting a new line. */
  1545. if (pp_buffer (pp)->line_length == 0)
  1546. {
  1547. pp_emit_prefix (pp);
  1548. if (pp_is_wrapping_line (pp))
  1549. while (start != end && *start == ' ')
  1550. ++start;
  1551. }
  1552. pp_append_r (pp, start, end - start);
  1553. }
  1554. /* Finishes constructing a NULL-terminated character string representing
  1555. the PRETTY-PRINTED text. */
  1556. const char *
  1557. pp_formatted_text (pretty_printer *pp)
  1558. {
  1559. return output_buffer_formatted_text (pp_buffer (pp));
  1560. }
  1561. /* Return a pointer to the last character emitted in PRETTY-PRINTER's
  1562. output area. A NULL pointer means no character available. */
  1563. const char *
  1564. pp_last_position_in_text (const pretty_printer *pp)
  1565. {
  1566. return output_buffer_last_position_in_text (pp_buffer (pp));
  1567. }
  1568. /* Return the amount of characters PRETTY-PRINTER can accept to
  1569. make a full line. Meaningful only in line-wrapping mode. */
  1570. int
  1571. pp_remaining_character_count_for_line (pretty_printer *pp)
  1572. {
  1573. return pp->maximum_length - pp_buffer (pp)->line_length;
  1574. }
  1575. /* Format a message into BUFFER a la printf. */
  1576. void
  1577. pp_printf (pretty_printer *pp, const char *msg, ...)
  1578. {
  1579. text_info text;
  1580. va_list ap;
  1581. va_start (ap, msg);
  1582. text.err_no = errno;
  1583. text.args_ptr = &ap;
  1584. text.format_spec = msg;
  1585. pp_format (pp, &text);
  1586. pp_output_formatted_text (pp);
  1587. va_end (ap);
  1588. }
  1589. /* Output MESSAGE verbatim into BUFFER. */
  1590. void
  1591. pp_verbatim (pretty_printer *pp, const char *msg, ...)
  1592. {
  1593. text_info text;
  1594. va_list ap;
  1595. va_start (ap, msg);
  1596. text.err_no = errno;
  1597. text.args_ptr = &ap;
  1598. text.format_spec = msg;
  1599. pp_format_verbatim (pp, &text);
  1600. va_end (ap);
  1601. }
  1602. /* Have PRETTY-PRINTER start a new line. */
  1603. void
  1604. pp_newline (pretty_printer *pp)
  1605. {
  1606. obstack_1grow (pp_buffer (pp)->obstack, '\n');
  1607. pp_needs_newline (pp) = false;
  1608. pp_buffer (pp)->line_length = 0;
  1609. }
  1610. /* Have PRETTY-PRINTER add a CHARACTER. */
  1611. void
  1612. pp_character (pretty_printer *pp, int c)
  1613. {
  1614. if (pp_is_wrapping_line (pp)
  1615. /* If printing UTF-8, don't wrap in the middle of a sequence. */
  1616. && (((unsigned int) c) & 0xC0) != 0x80
  1617. && pp_remaining_character_count_for_line (pp) <= 0)
  1618. {
  1619. pp_newline (pp);
  1620. if (ISSPACE (c))
  1621. return;
  1622. }
  1623. obstack_1grow (pp_buffer (pp)->obstack, c);
  1624. ++pp_buffer (pp)->line_length;
  1625. }
  1626. /* Append a STRING to the output area of PRETTY-PRINTER; the STRING may
  1627. be line-wrapped if in appropriate mode. */
  1628. void
  1629. pp_string (pretty_printer *pp, const char *str)
  1630. {
  1631. gcc_checking_assert (str);
  1632. pp_maybe_wrap_text (pp, str, str + strlen (str));
  1633. }
  1634. /* Append the leading N characters of STRING to the output area of
  1635. PRETTY-PRINTER, quoting in hexadecimal non-printable characters.
  1636. Setting N = -1 is as if N were set to strlen (STRING). The STRING
  1637. may be line-wrapped if in appropriate mode. */
  1638. static void
  1639. pp_quoted_string (pretty_printer *pp, const char *str, size_t n /* = -1 */)
  1640. {
  1641. gcc_checking_assert (str);
  1642. const char *last = str;
  1643. const char *ps;
  1644. /* Compute the length if not specified. */
  1645. if (n == (size_t) -1)
  1646. n = strlen (str);
  1647. for (ps = str; n; ++ps, --n)
  1648. {
  1649. if (ISPRINT (*ps))
  1650. continue;
  1651. /* Don't escape a valid UTF-8 extended char. */
  1652. const unsigned char *ups = (const unsigned char *) ps;
  1653. if (*ups & 0x80)
  1654. {
  1655. unsigned int extended_char;
  1656. const int valid_utf8_len = decode_utf8_char (ups, n, &extended_char);
  1657. if (valid_utf8_len > 0)
  1658. {
  1659. ps += valid_utf8_len - 1;
  1660. n -= valid_utf8_len - 1;
  1661. continue;
  1662. }
  1663. }
  1664. if (last < ps)
  1665. pp_maybe_wrap_text (pp, last, ps);
  1666. /* Append the hexadecimal value of the character. Allocate a buffer
  1667. that's large enough for a 32-bit char plus the hex prefix. */
  1668. char buf [11];
  1669. int n = sprintf (buf, "\\x%02x", (unsigned char)*ps);
  1670. pp_maybe_wrap_text (pp, buf, buf + n);
  1671. last = ps + 1;
  1672. }
  1673. pp_maybe_wrap_text (pp, last, ps);
  1674. }
  1675. /* Maybe print out a whitespace if needed. */
  1676. void
  1677. pp_maybe_space (pretty_printer *pp)
  1678. {
  1679. if (pp->padding != pp_none)
  1680. {
  1681. pp_space (pp);
  1682. pp->padding = pp_none;
  1683. }
  1684. }
  1685. // Add a newline to the pretty printer PP and flush formatted text.
  1686. void
  1687. pp_newline_and_flush (pretty_printer *pp)
  1688. {
  1689. pp_newline (pp);
  1690. pp_flush (pp);
  1691. pp_needs_newline (pp) = false;
  1692. }
  1693. // Add a newline to the pretty printer PP, followed by indentation.
  1694. void
  1695. pp_newline_and_indent (pretty_printer *pp, int n)
  1696. {
  1697. pp_indentation (pp) += n;
  1698. pp_newline (pp);
  1699. pp_indent (pp);
  1700. pp_needs_newline (pp) = false;
  1701. }
  1702. // Add separator C, followed by a single whitespace.
  1703. void
  1704. pp_separate_with (pretty_printer *pp, char c)
  1705. {
  1706. pp_character (pp, c);
  1707. pp_space (pp);
  1708. }
  1709. /* Add a localized open quote, and if SHOW_COLOR is true, begin colorizing
  1710. using the "quote" color. */
  1711. void
  1712. pp_begin_quote (pretty_printer *pp, bool show_color)
  1713. {
  1714. pp_string (pp, open_quote);
  1715. pp_string (pp, colorize_start (show_color, "quote"));
  1716. }
  1717. /* If SHOW_COLOR is true, stop colorizing.
  1718. Add a localized close quote. */
  1719. void
  1720. pp_end_quote (pretty_printer *pp, bool show_color)
  1721. {
  1722. pp_string (pp, colorize_stop (show_color));
  1723. pp_string (pp, close_quote);
  1724. }
  1725. /* The string starting at P has LEN (at least 1) bytes left; if they
  1726. start with a valid UTF-8 sequence, return the length of that
  1727. sequence and set *VALUE to the value of that sequence, and
  1728. otherwise return 0 and set *VALUE to (unsigned int) -1. */
  1729. static int
  1730. decode_utf8_char (const unsigned char *p, size_t len, unsigned int *value)
  1731. {
  1732. unsigned int t = *p;
  1733. if (len == 0)
  1734. abort ();
  1735. if (t & 0x80)
  1736. {
  1737. size_t utf8_len = 0;
  1738. unsigned int ch;
  1739. size_t i;
  1740. for (t = *p; t & 0x80; t <<= 1)
  1741. utf8_len++;
  1742. if (utf8_len > len || utf8_len < 2 || utf8_len > 6)
  1743. {
  1744. *value = (unsigned int) -1;
  1745. return 0;
  1746. }
  1747. ch = *p & ((1 << (7 - utf8_len)) - 1);
  1748. for (i = 1; i < utf8_len; i++)
  1749. {
  1750. unsigned int u = p[i];
  1751. if ((u & 0xC0) != 0x80)
  1752. {
  1753. *value = (unsigned int) -1;
  1754. return 0;
  1755. }
  1756. ch = (ch << 6) | (u & 0x3F);
  1757. }
  1758. if ( (ch <= 0x7F && utf8_len > 1)
  1759. || (ch <= 0x7FF && utf8_len > 2)
  1760. || (ch <= 0xFFFF && utf8_len > 3)
  1761. || (ch <= 0x1FFFFF && utf8_len > 4)
  1762. || (ch <= 0x3FFFFFF && utf8_len > 5)
  1763. || (ch >= 0xD800 && ch <= 0xDFFF))
  1764. {
  1765. *value = (unsigned int) -1;
  1766. return 0;
  1767. }
  1768. *value = ch;
  1769. return utf8_len;
  1770. }
  1771. else
  1772. {
  1773. *value = t;
  1774. return 1;
  1775. }
  1776. }
  1777. /* Allocator for identifier_to_locale and corresponding function to
  1778. free memory. */
  1779. void *(*identifier_to_locale_alloc) (size_t) = xmalloc;
  1780. void (*identifier_to_locale_free) (void *) = free;
  1781. /* Given IDENT, an identifier in the internal encoding, return a
  1782. version of IDENT suitable for diagnostics in the locale character
  1783. set: either IDENT itself, or a string, allocated using
  1784. identifier_to_locale_alloc, converted to the locale character set
  1785. and using escape sequences if not representable in the locale
  1786. character set or containing control characters or invalid byte
  1787. sequences. Existing backslashes in IDENT are not doubled, so the
  1788. result may not uniquely specify the contents of an arbitrary byte
  1789. sequence identifier. */
  1790. const char *
  1791. identifier_to_locale (const char *ident)
  1792. {
  1793. const unsigned char *uid = (const unsigned char *) ident;
  1794. size_t idlen = strlen (ident);
  1795. bool valid_printable_utf8 = true;
  1796. bool all_ascii = true;
  1797. size_t i;
  1798. for (i = 0; i < idlen;)
  1799. {
  1800. unsigned int c;
  1801. size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
  1802. if (utf8_len == 0 || c <= 0x1F || (c >= 0x7F && c <= 0x9F))
  1803. {
  1804. valid_printable_utf8 = false;
  1805. break;
  1806. }
  1807. if (utf8_len > 1)
  1808. all_ascii = false;
  1809. i += utf8_len;
  1810. }
  1811. /* If IDENT contains invalid UTF-8 sequences (which may occur with
  1812. attributes putting arbitrary byte sequences in identifiers), or
  1813. control characters, we use octal escape sequences for all bytes
  1814. outside printable ASCII. */
  1815. if (!valid_printable_utf8)
  1816. {
  1817. char *ret = (char *) identifier_to_locale_alloc (4 * idlen + 1);
  1818. char *p = ret;
  1819. for (i = 0; i < idlen; i++)
  1820. {
  1821. if (uid[i] > 0x1F && uid[i] < 0x7F)
  1822. *p++ = uid[i];
  1823. else
  1824. {
  1825. sprintf (p, "\\%03o", uid[i]);
  1826. p += 4;
  1827. }
  1828. }
  1829. *p = 0;
  1830. return ret;
  1831. }
  1832. /* Otherwise, if it is valid printable ASCII, or printable UTF-8
  1833. with the locale character set being UTF-8, IDENT is used. */
  1834. if (all_ascii || locale_utf8)
  1835. return ident;
  1836. /* Otherwise IDENT is converted to the locale character set if
  1837. possible. */
  1838. #if defined ENABLE_NLS && defined HAVE_LANGINFO_CODESET && HAVE_ICONV
  1839. if (locale_encoding != NULL)
  1840. {
  1841. iconv_t cd = iconv_open (locale_encoding, "UTF-8");
  1842. bool conversion_ok = true;
  1843. char *ret = NULL;
  1844. if (cd != (iconv_t) -1)
  1845. {
  1846. size_t ret_alloc = 4 * idlen + 1;
  1847. for (;;)
  1848. {
  1849. /* Repeat the whole conversion process as needed with
  1850. larger buffers so non-reversible transformations can
  1851. always be detected. */
  1852. ICONV_CONST char *inbuf = CONST_CAST (char *, ident);
  1853. char *outbuf;
  1854. size_t inbytesleft = idlen;
  1855. size_t outbytesleft = ret_alloc - 1;
  1856. size_t iconv_ret;
  1857. ret = (char *) identifier_to_locale_alloc (ret_alloc);
  1858. outbuf = ret;
  1859. if (iconv (cd, 0, 0, 0, 0) == (size_t) -1)
  1860. {
  1861. conversion_ok = false;
  1862. break;
  1863. }
  1864. iconv_ret = iconv (cd, &inbuf, &inbytesleft,
  1865. &outbuf, &outbytesleft);
  1866. if (iconv_ret == (size_t) -1 || inbytesleft != 0)
  1867. {
  1868. if (errno == E2BIG)
  1869. {
  1870. ret_alloc *= 2;
  1871. identifier_to_locale_free (ret);
  1872. ret = NULL;
  1873. continue;
  1874. }
  1875. else
  1876. {
  1877. conversion_ok = false;
  1878. break;
  1879. }
  1880. }
  1881. else if (iconv_ret != 0)
  1882. {
  1883. conversion_ok = false;
  1884. break;
  1885. }
  1886. /* Return to initial shift state. */
  1887. if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t) -1)
  1888. {
  1889. if (errno == E2BIG)
  1890. {
  1891. ret_alloc *= 2;
  1892. identifier_to_locale_free (ret);
  1893. ret = NULL;
  1894. continue;
  1895. }
  1896. else
  1897. {
  1898. conversion_ok = false;
  1899. break;
  1900. }
  1901. }
  1902. *outbuf = 0;
  1903. break;
  1904. }
  1905. iconv_close (cd);
  1906. if (conversion_ok)
  1907. return ret;
  1908. }
  1909. }
  1910. #endif
  1911. /* Otherwise, convert non-ASCII characters in IDENT to UCNs. */
  1912. {
  1913. char *ret = (char *) identifier_to_locale_alloc (10 * idlen + 1);
  1914. char *p = ret;
  1915. for (i = 0; i < idlen;)
  1916. {
  1917. unsigned int c;
  1918. size_t utf8_len = decode_utf8_char (&uid[i], idlen - i, &c);
  1919. if (utf8_len == 1)
  1920. *p++ = uid[i];
  1921. else
  1922. {
  1923. sprintf (p, "\\U%08x", c);
  1924. p += 10;
  1925. }
  1926. i += utf8_len;
  1927. }
  1928. *p = 0;
  1929. return ret;
  1930. }
  1931. }
  1932. /* Support for encoding URLs.
  1933. See egmontkob/Hyperlinks_in_Terminal_Emulators.md
  1934. ( https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda ).
  1935. > A hyperlink is opened upon encountering an OSC 8 escape sequence with
  1936. > the target URI. The syntax is
  1937. >
  1938. > OSC 8 ; params ; URI ST
  1939. >
  1940. > A hyperlink is closed with the same escape sequence, omitting the
  1941. > parameters and the URI but keeping the separators:
  1942. >
  1943. > OSC 8 ; ; ST
  1944. >
  1945. > OSC (operating system command) is typically ESC ].
  1946. Use BEL instead of ST, as that is currently rendered better in some
  1947. terminal emulators that don't support OSC 8, like konsole. */
  1948. /* If URL-printing is enabled, write an "open URL" escape sequence to PP
  1949. for the given URL. */
  1950. void
  1951. pp_begin_url (pretty_printer *pp, const char *url)
  1952. {
  1953. switch (pp->url_format)
  1954. {
  1955. case URL_FORMAT_NONE:
  1956. break;
  1957. case URL_FORMAT_ST:
  1958. pp_string (pp, "\33]8;;");
  1959. pp_string (pp, url);
  1960. pp_string (pp, "\33\\");
  1961. break;
  1962. case URL_FORMAT_BEL:
  1963. pp_string (pp, "\33]8;;");
  1964. pp_string (pp, url);
  1965. pp_string (pp, "\a");
  1966. break;
  1967. default:
  1968. gcc_unreachable ();
  1969. }
  1970. }
  1971. /* Helper function for pp_end_url and pp_format, return the "close URL" escape
  1972. sequence string. */
  1973. static const char *
  1974. get_end_url_string (pretty_printer *pp)
  1975. {
  1976. switch (pp->url_format)
  1977. {
  1978. case URL_FORMAT_NONE:
  1979. return "";
  1980. case URL_FORMAT_ST:
  1981. return "\33]8;;\33\\";
  1982. case URL_FORMAT_BEL:
  1983. return "\33]8;;\a";
  1984. default:
  1985. gcc_unreachable ();
  1986. }
  1987. }
  1988. /* If URL-printing is enabled, write a "close URL" escape sequence to PP. */
  1989. void
  1990. pp_end_url (pretty_printer *pp)
  1991. {
  1992. if (pp->url_format != URL_FORMAT_NONE)
  1993. pp_string (pp, get_end_url_string (pp));
  1994. }
  1995. #if CHECKING_P
  1996. namespace selftest {
  1997. /* Smoketest for pretty_printer. */
  1998. static void
  1999. test_basic_printing ()
  2000. {
  2001. pretty_printer pp;
  2002. pp_string (&pp, "hello");
  2003. pp_space (&pp);
  2004. pp_string (&pp, "world");
  2005. ASSERT_STREQ ("hello world", pp_formatted_text (&pp));
  2006. }
  2007. /* Helper function for testing pp_format.
  2008. Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
  2009. prints EXPECTED, assuming that pp_show_color is SHOW_COLOR. */
  2010. static void
  2011. assert_pp_format_va (const location &loc, const char *expected,
  2012. bool show_color, const char *fmt, va_list *ap)
  2013. {
  2014. pretty_printer pp;
  2015. text_info ti;
  2016. rich_location rich_loc (line_table, UNKNOWN_LOCATION);
  2017. ti.format_spec = fmt;
  2018. ti.args_ptr = ap;
  2019. ti.err_no = 0;
  2020. ti.x_data = NULL;
  2021. ti.m_richloc = &rich_loc;
  2022. pp_show_color (&pp) = show_color;
  2023. pp_format (&pp, &ti);
  2024. pp_output_formatted_text (&pp);
  2025. ASSERT_STREQ_AT (loc, expected, pp_formatted_text (&pp));
  2026. }
  2027. /* Verify that pp_format (FMT, ...) followed by pp_output_formatted_text
  2028. prints EXPECTED, with show_color disabled. */
  2029. static void
  2030. assert_pp_format (const location &loc, const char *expected,
  2031. const char *fmt, ...)
  2032. {
  2033. va_list ap;
  2034. va_start (ap, fmt);
  2035. assert_pp_format_va (loc, expected, false, fmt, &ap);
  2036. va_end (ap);
  2037. }
  2038. /* As above, but with colorization enabled. */
  2039. static void
  2040. assert_pp_format_colored (const location &loc, const char *expected,
  2041. const char *fmt, ...)
  2042. {
  2043. /* The tests of colorization assume the default color scheme.
  2044. If GCC_COLORS is set, then the colors have potentially been
  2045. overridden; skip the test. */
  2046. if (getenv ("GCC_COLORS"))
  2047. return;
  2048. va_list ap;
  2049. va_start (ap, fmt);
  2050. assert_pp_format_va (loc, expected, true, fmt, &ap);
  2051. va_end (ap);
  2052. }
  2053. /* Helper function for calling testing pp_format,
  2054. by calling assert_pp_format with various numbers of arguments.
  2055. These exist mostly to avoid having to write SELFTEST_LOCATION
  2056. throughout test_pp_format. */
  2057. #define ASSERT_PP_FORMAT_1(EXPECTED, FMT, ARG1) \
  2058. SELFTEST_BEGIN_STMT \
  2059. assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
  2060. (ARG1)); \
  2061. SELFTEST_END_STMT
  2062. #define ASSERT_PP_FORMAT_2(EXPECTED, FMT, ARG1, ARG2) \
  2063. SELFTEST_BEGIN_STMT \
  2064. assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
  2065. (ARG1), (ARG2)); \
  2066. SELFTEST_END_STMT
  2067. #define ASSERT_PP_FORMAT_3(EXPECTED, FMT, ARG1, ARG2, ARG3) \
  2068. SELFTEST_BEGIN_STMT \
  2069. assert_pp_format ((SELFTEST_LOCATION), (EXPECTED), (FMT), \
  2070. (ARG1), (ARG2), (ARG3)); \
  2071. SELFTEST_END_STMT
  2072. /* Verify that pp_format works, for various format codes. */
  2073. static void
  2074. test_pp_format ()
  2075. {
  2076. /* Avoid introducing locale-specific differences in the results
  2077. by hardcoding open_quote and close_quote. */
  2078. auto_fix_quotes fix_quotes;
  2079. /* Verify that plain text is passed through unchanged. */
  2080. assert_pp_format (SELFTEST_LOCATION, "unformatted", "unformatted");
  2081. /* Verify various individual format codes, in the order listed in the
  2082. comment for pp_format above. For each code, we append a second
  2083. argument with a known bit pattern (0x12345678), to ensure that we
  2084. are consuming arguments correctly. */
  2085. ASSERT_PP_FORMAT_2 ("-27 12345678", "%d %x", -27, 0x12345678);
  2086. ASSERT_PP_FORMAT_2 ("-5 12345678", "%i %x", -5, 0x12345678);
  2087. ASSERT_PP_FORMAT_2 ("10 12345678", "%u %x", 10, 0x12345678);
  2088. ASSERT_PP_FORMAT_2 ("17 12345678", "%o %x", 15, 0x12345678);
  2089. ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%x %x", 0xcafebabe, 0x12345678);
  2090. ASSERT_PP_FORMAT_2 ("-27 12345678", "%ld %x", (long)-27, 0x12345678);
  2091. ASSERT_PP_FORMAT_2 ("-5 12345678", "%li %x", (long)-5, 0x12345678);
  2092. ASSERT_PP_FORMAT_2 ("10 12345678", "%lu %x", (long)10, 0x12345678);
  2093. ASSERT_PP_FORMAT_2 ("17 12345678", "%lo %x", (long)15, 0x12345678);
  2094. ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%lx %x", (long)0xcafebabe,
  2095. 0x12345678);
  2096. ASSERT_PP_FORMAT_2 ("-27 12345678", "%lld %x", (long long)-27, 0x12345678);
  2097. ASSERT_PP_FORMAT_2 ("-5 12345678", "%lli %x", (long long)-5, 0x12345678);
  2098. ASSERT_PP_FORMAT_2 ("10 12345678", "%llu %x", (long long)10, 0x12345678);
  2099. ASSERT_PP_FORMAT_2 ("17 12345678", "%llo %x", (long long)15, 0x12345678);
  2100. ASSERT_PP_FORMAT_2 ("cafebabe 12345678", "%llx %x", (long long)0xcafebabe,
  2101. 0x12345678);
  2102. ASSERT_PP_FORMAT_2 ("-27 12345678", "%wd %x", (HOST_WIDE_INT)-27, 0x12345678);
  2103. ASSERT_PP_FORMAT_2 ("-5 12345678", "%wi %x", (HOST_WIDE_INT)-5, 0x12345678);
  2104. ASSERT_PP_FORMAT_2 ("10 12345678", "%wu %x", (unsigned HOST_WIDE_INT)10,
  2105. 0x12345678);
  2106. ASSERT_PP_FORMAT_2 ("17 12345678", "%wo %x", (HOST_WIDE_INT)15, 0x12345678);
  2107. ASSERT_PP_FORMAT_2 ("0xcafebabe 12345678", "%wx %x", (HOST_WIDE_INT)0xcafebabe,
  2108. 0x12345678);
  2109. ASSERT_PP_FORMAT_2 ("1.000000 12345678", "%f %x", 1.0, 0x12345678);
  2110. ASSERT_PP_FORMAT_2 ("A 12345678", "%c %x", 'A', 0x12345678);
  2111. ASSERT_PP_FORMAT_2 ("hello world 12345678", "%s %x", "hello world",
  2112. 0x12345678);
  2113. /* Not nul-terminated. */
  2114. char arr[5] = { '1', '2', '3', '4', '5' };
  2115. ASSERT_PP_FORMAT_3 ("123 12345678", "%.*s %x", 3, arr, 0x12345678);
  2116. ASSERT_PP_FORMAT_3 ("1234 12345678", "%.*s %x", -1, "1234", 0x12345678);
  2117. ASSERT_PP_FORMAT_3 ("12345 12345678", "%.*s %x", 7, "12345", 0x12345678);
  2118. /* We can't test for %p; the pointer is printed in an implementation-defined
  2119. manner. */
  2120. ASSERT_PP_FORMAT_2 ("normal colored normal 12345678",
  2121. "normal %rcolored%R normal %x",
  2122. "error", 0x12345678);
  2123. assert_pp_format_colored
  2124. (SELFTEST_LOCATION,
  2125. "normal \33[01;31m\33[Kcolored\33[m\33[K normal 12345678",
  2126. "normal %rcolored%R normal %x", "error", 0x12345678);
  2127. /* TODO:
  2128. %m: strerror(text->err_no) - does not consume a value from args_ptr. */
  2129. ASSERT_PP_FORMAT_1 ("% 12345678", "%% %x", 0x12345678);
  2130. ASSERT_PP_FORMAT_1 ("` 12345678", "%< %x", 0x12345678);
  2131. ASSERT_PP_FORMAT_1 ("' 12345678", "%> %x", 0x12345678);
  2132. ASSERT_PP_FORMAT_1 ("' 12345678", "%' %x", 0x12345678);
  2133. ASSERT_PP_FORMAT_3 ("abc 12345678", "%.*s %x", 3, "abcdef", 0x12345678);
  2134. ASSERT_PP_FORMAT_2 ("abc 12345678", "%.3s %x", "abcdef", 0x12345678);
  2135. /* Verify flag 'q'. */
  2136. ASSERT_PP_FORMAT_2 ("`foo' 12345678", "%qs %x", "foo", 0x12345678);
  2137. assert_pp_format_colored (SELFTEST_LOCATION,
  2138. "`\33[01m\33[Kfoo\33[m\33[K' 12345678", "%qs %x",
  2139. "foo", 0x12345678);
  2140. /* Verify "%@". */
  2141. {
  2142. diagnostic_event_id_t first (2);
  2143. diagnostic_event_id_t second (7);
  2144. ASSERT_PP_FORMAT_2 ("first `free' at (3); second `free' at (8)",
  2145. "first %<free%> at %@; second %<free%> at %@",
  2146. &first, &second);
  2147. assert_pp_format_colored
  2148. (SELFTEST_LOCATION,
  2149. "first `free' at (3);"
  2150. " second `free' at (8)",
  2151. "first %<free%> at %@; second %<free%> at %@",
  2152. &first, &second);
  2153. }
  2154. /* Verify %Z. */
  2155. int v[] = { 1, 2, 3 };
  2156. ASSERT_PP_FORMAT_3 ("1, 2, 3 12345678", "%Z %x", v, 3, 0x12345678);
  2157. int v2[] = { 0 };
  2158. ASSERT_PP_FORMAT_3 ("0 12345678", "%Z %x", v2, 1, 0x12345678);
  2159. /* Verify that combinations work, along with unformatted text. */
  2160. assert_pp_format (SELFTEST_LOCATION,
  2161. "the quick brown fox jumps over the lazy dog",
  2162. "the %s %s %s jumps over the %s %s",
  2163. "quick", "brown", "fox", "lazy", "dog");
  2164. assert_pp_format (SELFTEST_LOCATION, "item 3 of 7", "item %i of %i", 3, 7);
  2165. assert_pp_format (SELFTEST_LOCATION, "problem with `bar' at line 10",
  2166. "problem with %qs at line %i", "bar", 10);
  2167. }
  2168. /* A subclass of pretty_printer for use by test_prefixes_and_wrapping. */
  2169. class test_pretty_printer : public pretty_printer
  2170. {
  2171. public:
  2172. test_pretty_printer (enum diagnostic_prefixing_rule_t rule,
  2173. int max_line_length)
  2174. {
  2175. pp_set_prefix (this, xstrdup ("PREFIX: "));
  2176. wrapping.rule = rule;
  2177. pp_set_line_maximum_length (this, max_line_length);
  2178. }
  2179. };
  2180. /* Verify that the various values of enum diagnostic_prefixing_rule_t work
  2181. as expected, with and without line wrapping. */
  2182. static void
  2183. test_prefixes_and_wrapping ()
  2184. {
  2185. /* Tests of the various prefixing rules, without wrapping.
  2186. Newlines embedded in pp_string don't affect it; we have to
  2187. explicitly call pp_newline. */
  2188. {
  2189. test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 0);
  2190. pp_string (&pp, "the quick brown fox");
  2191. pp_newline (&pp);
  2192. pp_string (&pp, "jumps over the lazy dog");
  2193. pp_newline (&pp);
  2194. ASSERT_STREQ (pp_formatted_text (&pp),
  2195. "PREFIX: the quick brown fox\n"
  2196. " jumps over the lazy dog\n");
  2197. }
  2198. {
  2199. test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 0);
  2200. pp_string (&pp, "the quick brown fox");
  2201. pp_newline (&pp);
  2202. pp_string (&pp, "jumps over the lazy dog");
  2203. pp_newline (&pp);
  2204. ASSERT_STREQ (pp_formatted_text (&pp),
  2205. "the quick brown fox\n"
  2206. "jumps over the lazy dog\n");
  2207. }
  2208. {
  2209. test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 0);
  2210. pp_string (&pp, "the quick brown fox");
  2211. pp_newline (&pp);
  2212. pp_string (&pp, "jumps over the lazy dog");
  2213. pp_newline (&pp);
  2214. ASSERT_STREQ (pp_formatted_text (&pp),
  2215. "PREFIX: the quick brown fox\n"
  2216. "PREFIX: jumps over the lazy dog\n");
  2217. }
  2218. /* Tests of the various prefixing rules, with wrapping. */
  2219. {
  2220. test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_ONCE, 20);
  2221. pp_string (&pp, "the quick brown fox jumps over the lazy dog");
  2222. pp_newline (&pp);
  2223. pp_string (&pp, "able was I ere I saw elba");
  2224. pp_newline (&pp);
  2225. ASSERT_STREQ (pp_formatted_text (&pp),
  2226. "PREFIX: the quick \n"
  2227. " brown fox jumps \n"
  2228. " over the lazy \n"
  2229. " dog\n"
  2230. " able was I ere I \n"
  2231. " saw elba\n");
  2232. }
  2233. {
  2234. test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_NEVER, 20);
  2235. pp_string (&pp, "the quick brown fox jumps over the lazy dog");
  2236. pp_newline (&pp);
  2237. pp_string (&pp, "able was I ere I saw elba");
  2238. pp_newline (&pp);
  2239. ASSERT_STREQ (pp_formatted_text (&pp),
  2240. "the quick brown fox \n"
  2241. "jumps over the lazy \n"
  2242. "dog\n"
  2243. "able was I ere I \n"
  2244. "saw elba\n");
  2245. }
  2246. {
  2247. test_pretty_printer pp (DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE, 20);
  2248. pp_string (&pp, "the quick brown fox jumps over the lazy dog");
  2249. pp_newline (&pp);
  2250. pp_string (&pp, "able was I ere I saw elba");
  2251. pp_newline (&pp);
  2252. ASSERT_STREQ (pp_formatted_text (&pp),
  2253. "PREFIX: the quick brown fox jumps over the lazy dog\n"
  2254. "PREFIX: able was I ere I saw elba\n");
  2255. }
  2256. }
  2257. /* Verify that URL-printing works as expected. */
  2258. void
  2259. test_urls ()
  2260. {
  2261. {
  2262. pretty_printer pp;
  2263. pp.url_format = URL_FORMAT_NONE;
  2264. pp_begin_url (&pp, "http://example.com");
  2265. pp_string (&pp, "This is a link");
  2266. pp_end_url (&pp);
  2267. ASSERT_STREQ ("This is a link",
  2268. pp_formatted_text (&pp));
  2269. }
  2270. {
  2271. pretty_printer pp;
  2272. pp.url_format = URL_FORMAT_ST;
  2273. pp_begin_url (&pp, "http://example.com");
  2274. pp_string (&pp, "This is a link");
  2275. pp_end_url (&pp);
  2276. ASSERT_STREQ ("\33]8;;http://example.com\33\\This is a link\33]8;;\33\\",
  2277. pp_formatted_text (&pp));
  2278. }
  2279. {
  2280. pretty_printer pp;
  2281. pp.url_format = URL_FORMAT_BEL;
  2282. pp_begin_url (&pp, "http://example.com");
  2283. pp_string (&pp, "This is a link");
  2284. pp_end_url (&pp);
  2285. ASSERT_STREQ ("\33]8;;http://example.com\aThis is a link\33]8;;\a",
  2286. pp_formatted_text (&pp));
  2287. }
  2288. }
  2289. /* Test multibyte awareness. */
  2290. static void test_utf8 ()
  2291. {
  2292. /* Check that pp_quoted_string leaves valid UTF-8 alone. */
  2293. {
  2294. pretty_printer pp;
  2295. const char *s = "\xf0\x9f\x98\x82";
  2296. pp_quoted_string (&pp, s);
  2297. ASSERT_STREQ (pp_formatted_text (&pp), s);
  2298. }
  2299. /* Check that pp_quoted_string escapes non-UTF-8 nonprintable bytes. */
  2300. {
  2301. pretty_printer pp;
  2302. pp_quoted_string (&pp, "\xf0!\x9f\x98\x82");
  2303. ASSERT_STREQ (pp_formatted_text (&pp),
  2304. "\\xf0!\\x9f\\x98\\x82");
  2305. }
  2306. /* Check that pp_character will line-wrap at the beginning of a UTF-8
  2307. sequence, but not in the middle. */
  2308. {
  2309. pretty_printer pp (3);
  2310. const char s[] = "---\xf0\x9f\x98\x82";
  2311. for (int i = 0; i != sizeof (s) - 1; ++i)
  2312. pp_character (&pp, s[i]);
  2313. pp_newline (&pp);
  2314. for (int i = 1; i != sizeof (s) - 1; ++i)
  2315. pp_character (&pp, s[i]);
  2316. pp_character (&pp, '-');
  2317. ASSERT_STREQ (pp_formatted_text (&pp),
  2318. "---\n"
  2319. "\xf0\x9f\x98\x82\n"
  2320. "--\xf0\x9f\x98\x82\n"
  2321. "-");
  2322. }
  2323. }
  2324. /* Run all of the selftests within this file. */
  2325. void
  2326. pretty_print_c_tests ()
  2327. {
  2328. test_basic_printing ();
  2329. test_pp_format ();
  2330. test_prefixes_and_wrapping ();
  2331. test_urls ();
  2332. test_utf8 ();
  2333. }
  2334. } // namespace selftest
  2335. #endif /* CHECKING_P */