parser.c 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781
  1. /* Copyright 2010, 2011, 2012, 2013, 2014, 2015
  2. Free Software Foundation, Inc.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #include <string.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <ctype.h>
  17. #include "parser.h"
  18. #include "text.h"
  19. #include "input.h"
  20. #include "tree.h"
  21. #include "api.h"
  22. #include "errors.h"
  23. /* Utility functions */
  24. const char *whitespace_chars = " \t\f\r\n";
  25. const char *digit_chars = "0123456789";
  26. // [^\S\r\n] in Perl
  27. const char *whitespace_chars_except_newline = " \t\f";
  28. /* Check if the contents of S2 appear at S1). */
  29. int
  30. looking_at (char *s1, char *s2)
  31. {
  32. return !strncmp (s1, s2, strlen (s2));
  33. }
  34. /* Look for a sequence of alphanumeric characters or hyphens, where the
  35. first isn't a hyphen. This is the format of (non-single-character) Texinfo
  36. commands, but is also used elsewhere. Return value to be freed by caller.
  37. *PTR is advanced past the read name. Return 0 if name is invalid. */
  38. // 4161
  39. char *
  40. read_command_name (char **ptr)
  41. {
  42. char *p = *ptr, *q;
  43. char *ret = 0;
  44. q = p;
  45. if (!isalnum (*q))
  46. return 0; /* Invalid. */
  47. while (isalnum (*q) || *q == '-' || *q == '_')
  48. q++;
  49. ret = strndup (p, q - p);
  50. p = q;
  51. *ptr = p;
  52. return ret;
  53. }
  54. /* Current node and section. */
  55. ELEMENT *current_node = 0;
  56. ELEMENT *current_section = 0;
  57. /* Conditional stack. */
  58. enum command_id *conditional_stack;
  59. size_t conditional_number;
  60. size_t conditional_space;
  61. void
  62. push_conditional_stack (enum command_id cond)
  63. {
  64. if (conditional_number == conditional_space)
  65. {
  66. conditional_stack = realloc (conditional_stack,
  67. (conditional_space += 5)
  68. * sizeof (enum command_id));
  69. if (!conditional_stack)
  70. abort ();
  71. }
  72. conditional_stack[conditional_number++] = cond;
  73. }
  74. enum command_id
  75. pop_conditional_stack (void)
  76. {
  77. if (conditional_number == 0)
  78. return CM_NONE;
  79. return conditional_stack[--conditional_number];
  80. }
  81. /* Counters */
  82. COUNTER count_remaining_args;
  83. COUNTER count_items;
  84. COUNTER count_cells;
  85. /* Information that is not local to where it is set in the Texinfo input,
  86. for example document language and encoding. */
  87. GLOBAL_INFO global_info;
  88. char *global_clickstyle = "arrow";
  89. char *global_documentlanguage = "";
  90. enum kbd_enum global_kbdinputstyle = kbd_distinct;
  91. void
  92. wipe_global_info (void)
  93. {
  94. global_clickstyle = "arrow";
  95. global_kbdinputstyle = kbd_distinct;
  96. global_documentlanguage = "";
  97. memset (&global_info, 0, sizeof (global_info));
  98. }
  99. /* 835 */
  100. void
  101. parse_texi_file (char *filename)
  102. {
  103. char *p, *q;
  104. char *linep, *line = 0;
  105. ELEMENT *root = new_element (ET_text_root);
  106. ELEMENT *preamble = 0;
  107. char c;
  108. int status;
  109. status = input_push_file (filename);
  110. if (status)
  111. {
  112. /* TODO document_error */
  113. abort ();
  114. }
  115. //filename = strdup (filename);
  116. /* Strip off a leading directory path, by looking for the last
  117. '/' in filename. */
  118. p = 0;
  119. q = strchr (filename, '/');
  120. while (q)
  121. {
  122. p = q;
  123. q = strchr (q + 1, '/');
  124. }
  125. if (p)
  126. {
  127. c = *p;
  128. *p = '\0';
  129. add_include_directory (filename);
  130. *p = c;
  131. }
  132. /* Check for preamble. */
  133. while (1)
  134. {
  135. ELEMENT *l;
  136. /* FIXME: _next_text isn't used in Perl. */
  137. free (line);
  138. line = next_text ();
  139. if (!line)
  140. abort (); /* Empty file? */
  141. linep = line;
  142. linep += strspn (linep, whitespace_chars);
  143. if (*linep && !looking_at (linep, "\\input"))
  144. {
  145. /* This line is not part of the preamble. Shove back
  146. into input stream. */
  147. input_push (line, 0, line_nr.file_name, line_nr.line_nr);
  148. break;
  149. }
  150. if (!preamble)
  151. preamble = new_element (ET_preamble);
  152. l = new_element (ET_preamble_text);
  153. text_append (&l->text, line);
  154. add_to_element_contents (preamble, l);
  155. }
  156. if (preamble)
  157. add_to_element_contents (root, preamble);
  158. Root = parse_texi (root);
  159. } /* 916 */
  160. int
  161. begin_paragraph_p (ELEMENT *current)
  162. {
  163. return (current->type == ET_NONE /* "True for @-commands" */
  164. || current->type == ET_before_item
  165. || current->type == ET_text_root
  166. || current->type == ET_document_root
  167. || current->type == ET_brace_command_context)
  168. && in_paragraph_context (current_context ());
  169. }
  170. /* Line 1146 */
  171. /* If in a context where paragraphs are to be started, start a new
  172. paragraph. */
  173. ELEMENT *
  174. begin_paragraph (ELEMENT *current)
  175. {
  176. if (begin_paragraph_p (current))
  177. {
  178. ELEMENT *e;
  179. enum command_id indent = 0;
  180. /* Check if an @indent precedes the paragraph (to record it
  181. in the 'extra' key). */
  182. if (current->contents.number > 0)
  183. {
  184. int i = current->contents.number - 1;
  185. while (i >= 0)
  186. {
  187. ELEMENT *child = contents_child_by_index (current, i);
  188. if (child->type == ET_empty_line
  189. || child->type == ET_paragraph)
  190. break;
  191. if (close_paragraph_command(child->cmd))
  192. break;
  193. if (child->cmd == CM_indent
  194. || child->cmd == CM_noindent)
  195. {
  196. indent = child->cmd;
  197. break;
  198. }
  199. i--;
  200. }
  201. }
  202. e = new_element (ET_paragraph);
  203. if (indent)
  204. add_extra_string (e, indent == CM_indent ? "indent" : "noindent", "1");
  205. add_to_element_contents (current, e);
  206. current = e;
  207. debug ("PARAGRAPH");
  208. }
  209. return current;
  210. }
  211. // 1190
  212. ELEMENT *
  213. begin_preformatted (ELEMENT *current)
  214. {
  215. if (current_context() == ct_preformatted
  216. || current_context() == ct_rawpreformatted)
  217. {
  218. ELEMENT *e;
  219. enum element_type et;
  220. if (current_context() == ct_preformatted)
  221. et = ET_preformatted;
  222. else
  223. et = ET_rawpreformatted;
  224. e = new_element (et);
  225. add_to_element_contents (current, e);
  226. current = e;
  227. debug ("PREFORMATTED %s", et == ET_preformatted ? "preformatted"
  228. : "rawpreformatted");
  229. }
  230. return current;
  231. }
  232. /* 1310 */
  233. ELEMENT *
  234. end_paragraph (ELEMENT *current,
  235. enum command_id closed_command,
  236. enum command_id interrupting_command)
  237. {
  238. current = close_all_style_commands (current,
  239. closed_command, interrupting_command);
  240. if (current->type == ET_paragraph)
  241. {
  242. debug ("CLOSE PARA");
  243. current = current->parent;
  244. }
  245. return current;
  246. }
  247. /* 1328 */
  248. ELEMENT *
  249. end_preformatted (ELEMENT *current,
  250. enum command_id closed_command,
  251. enum command_id interrupting_command)
  252. {
  253. current = close_all_style_commands (current,
  254. closed_command, interrupting_command);
  255. if (current->type == ET_preformatted
  256. || current->type == ET_rawpreformatted)
  257. {
  258. debug ("CLOSE PREFORMATTED %s",
  259. current->type == ET_preformatted ? "preformatted"
  260. : "rawpreformatted");
  261. if (current->contents.number == 0)
  262. {
  263. current = current->parent;
  264. destroy_element (pop_element_from_contents (current));
  265. debug ("popping");
  266. }
  267. else
  268. current = current->parent;
  269. }
  270. return current;
  271. }
  272. /* Line 1798 */
  273. /* Add TEXT to the contents of CURRENT, maybe starting a new paragraph. */
  274. ELEMENT *
  275. merge_text (ELEMENT *current, char *text)
  276. {
  277. int no_merge_with_following_text = 0;
  278. int leading_spaces = strspn (text, whitespace_chars);
  279. ELEMENT *last_child = last_contents_child (current);
  280. /* Is there a non-whitespace character in the line? */
  281. if (text[leading_spaces])
  282. {
  283. char *additional = 0;
  284. if (last_child
  285. && (last_child->type == ET_empty_line_after_command
  286. || last_child->type == ET_empty_spaces_after_command
  287. || last_child->type == ET_empty_spaces_before_argument
  288. || last_child->type == ET_empty_spaces_after_close_brace))
  289. {
  290. no_merge_with_following_text = 1;
  291. }
  292. if (leading_spaces)
  293. {
  294. additional = malloc (leading_spaces + 1);
  295. if (!additional)
  296. abort ();
  297. memcpy (additional, text, leading_spaces);
  298. additional[leading_spaces] = '\0';
  299. }
  300. if (abort_empty_line (&current, additional))
  301. text += leading_spaces;
  302. free (additional);
  303. current = begin_paragraph (current);
  304. }
  305. last_child = last_contents_child (current);
  306. if (last_child
  307. /* There is a difference between the text being defined and empty,
  308. and not defined at all. The latter is true for 'brace_command_arg'
  309. elements. We need either to make sure that we initialize all elements
  310. with text_append (&e->text, "") where we want merging with following
  311. text, or treat as a special case here.
  312. Unfortunately we can't make a special case for
  313. ET_empty_spaces_before_argument, because abort_empty_line above
  314. produces such an element that shouldn't be merged with. */
  315. && (last_child->text.space > 0
  316. && !strchr (last_child->text.text, '\n')
  317. ) //|| last_child->type == ET_empty_spaces_before_argument)
  318. && last_child->cmd != CM_value
  319. && !no_merge_with_following_text)
  320. {
  321. /* Append text to contents */
  322. text_append (&last_child->text, text);
  323. debug ("MERGED TEXT: %s|||", text);
  324. }
  325. else
  326. {
  327. ELEMENT *e = new_element (ET_NONE);
  328. text_append (&e->text, text);
  329. add_to_element_contents (current, e);
  330. debug ("NEW TEXT: %s|||", text);
  331. }
  332. return current;
  333. }
  334. /* 2106 */
  335. int
  336. abort_empty_line (ELEMENT **current_inout, char *additional_text)
  337. {
  338. ELEMENT *current = *current_inout;
  339. int retval;
  340. ELEMENT *last_child = last_contents_child (current);
  341. if (!additional_text)
  342. additional_text = "";
  343. if (last_child
  344. && (last_child->type == ET_empty_line
  345. || last_child->type == ET_empty_line_after_command
  346. || last_child->type == ET_empty_spaces_before_argument
  347. || last_child->type == ET_empty_spaces_after_close_brace))
  348. {
  349. debug ("ABORT EMPTY %s additional text |%s| "
  350. "current |%s|",
  351. element_type_name(last_child),
  352. additional_text,
  353. last_child->text.text);
  354. text_append (&last_child->text, additional_text);
  355. /* Remove element altogether if it's empty. */
  356. if (last_child->text.end == 0) //2121
  357. {
  358. KEY_PAIR *k = 0; ELEMENT *e;
  359. /* Remove extra key from either from current or current->parent. */
  360. if (current)
  361. k = lookup_extra_key (current, "spaces_before_argument");
  362. if (k && k->value == last_contents_child (current))
  363. {
  364. k->key = "";
  365. k->value = 0;
  366. k->type = extra_deleted;
  367. }
  368. else if (current->parent)
  369. {
  370. k = lookup_extra_key (current->parent, "spaces_before_argument");
  371. if (k && k->value == last_contents_child (current))
  372. {
  373. k->key = "";
  374. k->value = 0;
  375. k->type = extra_deleted;
  376. }
  377. }
  378. if (current)
  379. k = lookup_extra_key (current, "spaces_after_command");
  380. if (k && k->value == last_contents_child(current))
  381. {
  382. k->key = "";
  383. k->value = 0;
  384. k->type = extra_deleted;
  385. }
  386. else if (current->parent)
  387. {
  388. k = lookup_extra_key (current->parent, "spaces_after_command");
  389. if (k && k->value == last_contents_child (current))
  390. {
  391. k->key = "";
  392. k->value = 0;
  393. k->type = extra_deleted;
  394. }
  395. }
  396. e = pop_element_from_contents (current);
  397. e->parent = 0; e->parent_type = route_not_in_tree;
  398. destroy_element (e);
  399. /* TODO: Maybe we could avoid adding it in the first place? */
  400. }
  401. else if (last_child->type == ET_empty_line) //2132
  402. {
  403. last_child->type = begin_paragraph_p (current)
  404. ? ET_empty_spaces_before_paragraph : ET_NONE;
  405. }
  406. else if (last_child->type == ET_empty_line_after_command)
  407. {
  408. last_child->type = ET_empty_spaces_after_command;
  409. }
  410. retval = 1;
  411. }
  412. else
  413. retval = 0;
  414. *current_inout = current;
  415. return retval;
  416. }
  417. /* 2149 */
  418. /* Split any trailing whitespace on the last contents child of CURRENT into
  419. its own element, ET_spaces_at_end by default.
  420. This is used for the argument to a line command, and for the arguments to a
  421. brace command taking a given number of arguments.
  422. This helps with argument parsing as there will be no leading or trailing
  423. spaces.
  424. Also, "to help expansion disregard unuseful spaces". Could that mean
  425. macro expansion? */
  426. void
  427. isolate_last_space (ELEMENT *current, enum element_type element_type)
  428. {
  429. ELEMENT *last = last_contents_child (current);
  430. if (!element_type)
  431. element_type = ET_spaces_at_end;
  432. if (last)
  433. {
  434. int index = -1;
  435. ELEMENT *indexed_elt;
  436. /* If a "misc" (i.e. line) command is last on line, isolate the space in
  437. the element before it. This covers the case of a "@c" at the end
  438. of a line. */
  439. if (element_contents_number (current) > 1)
  440. {
  441. if (last->cmd)
  442. {
  443. if (command_flags(last) & CF_misc)
  444. index = -2;
  445. }
  446. }
  447. indexed_elt = contents_child_by_index (current, index);
  448. if (indexed_elt)
  449. {
  450. char *text = element_text (indexed_elt);
  451. if (!text || !*text)
  452. return;
  453. if (indexed_elt->type == ET_NONE)
  454. {
  455. int text_len = strlen (text);
  456. /* 2170 */
  457. /* Does the text end in whitespace? */
  458. if (strchr (whitespace_chars, text[text_len - 1]))
  459. {
  460. /* If text all whitespace */
  461. if (text[strspn (text, whitespace_chars)] == '\0')
  462. indexed_elt->type = element_type;
  463. else
  464. {
  465. /* 2173 */
  466. ELEMENT *new_spaces;
  467. int i, trailing_spaces;
  468. /* "strrcspn" */
  469. trailing_spaces = 0;
  470. for (i = strlen (text) - 1;
  471. i > 0 && strchr (whitespace_chars, text[i]);
  472. i--)
  473. trailing_spaces++;
  474. new_spaces = new_element (element_type);
  475. text_append_n (&new_spaces->text,
  476. text + text_len - trailing_spaces,
  477. trailing_spaces);
  478. text[text_len - trailing_spaces] = '\0';
  479. indexed_elt->text.end -= trailing_spaces;
  480. if (index == -1)
  481. add_to_element_contents (current, new_spaces);
  482. else
  483. insert_into_contents (current, new_spaces, -1);
  484. }
  485. }
  486. }
  487. }
  488. }
  489. }
  490. // 5467, also in Common.pm 1334
  491. /* Return a new element whose contents are the same as those of ORIGINAL,
  492. but with some elements representing empty spaces removed. Elements like
  493. these are used to represent some of the "content" extra keys. */
  494. ELEMENT *
  495. trim_spaces_comment_from_content (ELEMENT *original)
  496. {
  497. ELEMENT *trimmed;
  498. int i, j, k;
  499. enum element_type t;
  500. trimmed = new_element (ET_NONE);
  501. trimmed->parent_type = route_not_in_tree;
  502. if (original->contents.number == 0)
  503. return trimmed;
  504. i = 1;
  505. t = original->contents.list[0]->type;
  506. if (t != ET_empty_line_after_command
  507. && t != ET_empty_spaces_after_command
  508. && t != ET_empty_spaces_before_argument
  509. && t != ET_empty_space_at_end_def_bracketed
  510. && t != ET_empty_spaces_after_close_brace)
  511. i = 0;
  512. for (j = original->contents.number - 1; j >= 0; j--)
  513. {
  514. enum element_type t = original->contents.list[j]->type;
  515. if (original->contents.list[j]->cmd != CM_c
  516. && original->contents.list[j]->cmd != CM_comment
  517. && t != ET_spaces_at_end
  518. && t != ET_space_at_end_block_command)
  519. break;
  520. }
  521. for (k = i; k <= j; k++)
  522. {
  523. add_to_contents_as_array (trimmed, original->contents.list[k]);
  524. }
  525. return trimmed;
  526. }
  527. /* 3491 */
  528. /* Add an "ET_empty_line_after_command" element containing the whitespace at
  529. the beginning of the rest of the line. This element can be later changed to
  530. a "ET_empty_spaces_after_command" element in 'abort_empty_line' if more
  531. text follows on the line. Used after line commands or commands starting
  532. a block. */
  533. void
  534. start_empty_line_after_command (ELEMENT *current, char **line_inout,
  535. ELEMENT *command)
  536. {
  537. char *line = *line_inout;
  538. ELEMENT *e;
  539. int len;
  540. len = strspn (line, whitespace_chars_except_newline);
  541. e = new_element (ET_empty_line_after_command);
  542. add_to_element_contents (current, e);
  543. text_append_n (&e->text, line, len);
  544. line += len;
  545. if (command)
  546. {
  547. add_extra_element (e, "command", command);
  548. add_extra_element (command, "spaces_after_command", e);
  549. }
  550. *line_inout = line;
  551. }
  552. /* If the parent element takes a command as an argument, like
  553. @itemize @bullet. */
  554. int
  555. command_with_command_as_argument (ELEMENT *current)
  556. {
  557. return current->type == ET_block_line_arg
  558. && (current->parent->cmd == CM_itemize
  559. || item_line_command (current->parent->cmd));
  560. // && (current->contents.number == 1);
  561. // || current->contents.number == 2 and the first child's text is
  562. // all non-whitespace characters??
  563. }
  564. // 3633
  565. /* If INVALID_PARENT is defined, then that command was used in the input
  566. document and contained, incorrectly, a COMMAND command. Issue
  567. a warning message. */
  568. void
  569. mark_and_warn_invalid (enum command_id command,
  570. enum command_id invalid_parent,
  571. ELEMENT *marked_as_invalid_command)
  572. {
  573. if (invalid_parent)
  574. {
  575. line_warn ("@%s should not appear in @%s",
  576. command_name(command),
  577. command_name(invalid_parent));
  578. if (marked_as_invalid_command)
  579. add_extra_string (marked_as_invalid_command, "invalid_nesting", "1");
  580. }
  581. }
  582. /* Used at line 3755 */
  583. /* Check if line is "@end ..." for current command. If so, advance LINE. */
  584. int
  585. is_end_current_command (ELEMENT *current, char **line,
  586. enum command_id *end_cmd)
  587. {
  588. char *linep;
  589. char *cmdname;
  590. linep = *line;
  591. linep += strspn (linep, whitespace_chars);
  592. if (!looking_at (linep, "@end"))
  593. return 0;
  594. linep += 4;
  595. if (!strchr (whitespace_chars, *linep))
  596. return 0;
  597. linep += strspn (linep, whitespace_chars);
  598. if (!*linep)
  599. return 0;
  600. cmdname = read_command_name (&linep);
  601. *end_cmd = lookup_command (cmdname);
  602. free (cmdname);
  603. if (*end_cmd != current->cmd)
  604. return 0;
  605. *line = linep;
  606. return 1;
  607. }
  608. #define GET_A_NEW_LINE 0
  609. #define STILL_MORE_TO_PROCESS 1
  610. #define FINISHED_TOTALLY 2
  611. /* line 3725 */
  612. /* *LINEP is a pointer into the line being processed. It is advanced past any
  613. bytes processed. Return 0 when we need to read a new line. */
  614. int
  615. process_remaining_on_line (ELEMENT **current_inout, char **line_inout)
  616. {
  617. ELEMENT *current = *current_inout;
  618. char *line = *line_inout;
  619. char *line_after_command;
  620. int retval = 1; /* Return value of function */
  621. enum command_id end_cmd;
  622. char *p;
  623. enum command_id cmd = CM_NONE;
  624. /********* BLOCK_raw or (ignored) BLOCK_conditional ******************/
  625. /* If in raw block, or ignored conditional block. */
  626. // 3727
  627. if (command_flags(current) & CF_block
  628. && (command_data(current->cmd).data == BLOCK_raw
  629. || command_data(current->cmd).data == BLOCK_conditional))
  630. { /* 3730 */
  631. /* Check if we are using a macro within a macro. */
  632. if (current->cmd == CM_macro || current->cmd == CM_rmacro)
  633. {
  634. enum command_id cmd = 0;
  635. char *p = line;
  636. p += strspn (p, whitespace_chars);
  637. if (!strncmp (p, "@macro", strlen ("@macro")))
  638. {
  639. p += strlen ("@macro");
  640. cmd = CM_macro;
  641. }
  642. else if (!strncmp (p, "@rmacro", strlen ("@rmacro")))
  643. {
  644. p += strlen ("@rmacro");
  645. cmd = CM_rmacro;
  646. }
  647. if (cmd)
  648. {
  649. ELEMENT *e = new_element (ET_NONE);
  650. e->cmd = cmd;
  651. line = p;
  652. add_to_element_contents (current, e);
  653. add_extra_string (e, "arg_line", strdup (line));
  654. current = e;
  655. retval = GET_A_NEW_LINE;
  656. goto funexit;
  657. }
  658. }
  659. /* Else check for nested @ifset (so that @end ifset doesn't
  660. end the outermost @ifset). */
  661. if (current->cmd == CM_ifclear || current->cmd == CM_ifset
  662. || current->cmd == CM_ifcommanddefined
  663. || current->cmd == CM_ifcommandnotdefined)
  664. {
  665. ELEMENT *e;
  666. char *p = line;
  667. p += strspn (p, whitespace_chars);
  668. if (*p == '@'
  669. && !strncmp (p + 1, command_name(current->cmd),
  670. strlen (command_name(current->cmd))))
  671. {
  672. line = p + 1;
  673. p += strlen (command_name(current->cmd));
  674. e = new_element (ET_NONE);
  675. e->cmd = current->cmd;
  676. add_extra_string (e, "line", strdup (line));
  677. add_to_element_contents (current, e);
  678. current = e;
  679. retval = GET_A_NEW_LINE;
  680. goto funexit;
  681. }
  682. }
  683. /* 3755 Else check if line is "@end ..." for current command. */
  684. p = line;
  685. if (is_end_current_command (current, &line, &end_cmd))
  686. {
  687. ELEMENT *last_child;
  688. ELEMENT *raw_command = current;
  689. char *tmp = 0;
  690. last_child = last_contents_child (current);
  691. if (strchr (whitespace_chars, *p))
  692. {
  693. ELEMENT *e;
  694. int n = strspn (line, whitespace_chars);
  695. e = new_element (ET_raw);
  696. text_append_n (&e->text, line, n);
  697. line += n;
  698. line_warn ("@end %s should only appear at the "
  699. "beginning of a line", command_name(end_cmd));
  700. }
  701. else if (last_child
  702. && last_child->type == ET_raw
  703. && current->cmd != CM_verbatim)
  704. {
  705. if (last_child->text.end > 0
  706. && last_child->text.text[last_child->text.end - 1] == '\n')
  707. {
  708. ELEMENT *lrn;
  709. last_child->text.text[--last_child->text.end] = '\0';
  710. lrn = new_element (ET_last_raw_newline);
  711. text_append (&lrn->text, "\n");
  712. add_to_element_contents (current, lrn);
  713. }
  714. }
  715. // 3779
  716. /* 'line' is now advanced past the "@end ...". Check if
  717. there's anything after it. */
  718. p = line + strspn (line, whitespace_chars);
  719. if (*p && *p != '@')
  720. goto superfluous_arg;
  721. if (*p)
  722. {
  723. p++;
  724. tmp = read_command_name (&p);
  725. if (tmp && (!strcmp (tmp, "c") || !strcmp (tmp, "comment")))
  726. {
  727. }
  728. else if (*p && p[strspn (p, whitespace_chars)])
  729. {
  730. superfluous_arg:
  731. line_warn ("superfluous argument to @end %s: %s",
  732. command_name (current->cmd), line);
  733. }
  734. free (tmp);
  735. }
  736. /* For macros, define a new macro (unless we are in a nested
  737. macro definition). */
  738. if ((end_cmd == CM_macro || end_cmd == CM_rmacro)
  739. && (!current->parent
  740. || (current->parent->cmd != CM_macro
  741. && current->parent->cmd != CM_rmacro)))
  742. {
  743. char *name;
  744. enum command_id existing;
  745. if (current->args.number > 0)
  746. {
  747. name = element_text (args_child_by_index (current, 0));
  748. existing = lookup_command (name);
  749. if (existing)
  750. {
  751. MACRO *macro;
  752. macro = lookup_macro (existing);
  753. if (macro)
  754. {
  755. line_error_ext (1, &current->line_nr,
  756. "macro `%s' previously defined", name);
  757. line_error_ext (1, &macro->element->line_nr,
  758. "here is the previous definition of `%s'", name);
  759. }
  760. else if (!(existing & USER_COMMAND_BIT))
  761. {
  762. line_error_ext (1, &current->line_nr,
  763. "redefining Texinfo language command: @%s",
  764. name);
  765. }
  766. }
  767. if (!lookup_extra_key (current, "invalid_syntax"))
  768. {
  769. new_macro (name, current); // 3808
  770. }
  771. }
  772. }
  773. current = current->parent;
  774. /* Check for conditionals. */
  775. if (command_data(end_cmd).flags & CF_block
  776. && command_data(end_cmd).data == BLOCK_conditional)
  777. {
  778. // 3813 Remove an ignored block.
  779. ELEMENT *popped;
  780. popped = pop_element_from_contents (current);
  781. if (popped->cmd != end_cmd)
  782. abort(); //error
  783. destroy_element_and_children (popped);
  784. /* Ignore until end of line */
  785. if (!strchr (line, '\n'))
  786. {
  787. debug ("IGNORE CLOSE LINE");
  788. line = new_line ();
  789. }
  790. debug ("CLOSED conditional %s", command_name(end_cmd));
  791. retval = GET_A_NEW_LINE;
  792. goto funexit;
  793. }
  794. else
  795. {
  796. ELEMENT *e;
  797. int n;
  798. debug ("CLOSED raw %s", command_name(end_cmd)); // 3830
  799. e = new_element (ET_empty_line_after_command);
  800. n = strspn (line, whitespace_chars_except_newline);
  801. text_append_n (&e->text, line, n);
  802. line += n;
  803. add_extra_element (e, "command", raw_command);
  804. add_to_element_contents (current, e);
  805. }
  806. }
  807. else /* 3833 save the line verbatim */
  808. {
  809. ELEMENT *last = last_contents_child (current);
  810. /* Append to existing element only if the text is all
  811. whitespace. */
  812. if (last && last->type == ET_empty_line_after_command
  813. && line[strspn (line, whitespace_chars)] == '\0'
  814. && !strchr (last->text.text, '\n'))
  815. {
  816. text_append (&last->text, line);
  817. }
  818. else
  819. {
  820. ELEMENT *e;
  821. e = new_element (ET_raw);
  822. text_append (&e->text, line);
  823. add_to_element_contents (current, e);
  824. }
  825. retval = GET_A_NEW_LINE; /* 3844 */
  826. goto funexit;
  827. }
  828. } /********* BLOCK_raw or (ignored) BLOCK_conditional 3897 *************/
  829. /* Check if parent element is 'verb' */
  830. else if (current->parent && current->parent->cmd == CM_verb) /* 3847 */
  831. {
  832. char c;
  833. char *q;
  834. c = (char) current->parent->type;
  835. if (c)
  836. {
  837. /* Look forward for the delimiter character followed by a close
  838. brace. */
  839. q = line;
  840. while (1)
  841. {
  842. q = strchr (q, c);
  843. if (!q || q[1] == '}')
  844. break;
  845. q++;
  846. }
  847. }
  848. else
  849. {
  850. /* Look forward for a close brace. */
  851. q = strchr (line, '}');
  852. }
  853. if (q)
  854. {
  855. /* Save up to the delimiter character. */
  856. if (q != line)
  857. {
  858. ELEMENT *e = new_element (ET_raw);
  859. text_append_n (&e->text, line, q - line);
  860. add_to_element_contents (current, e);
  861. }
  862. debug ("END VERB");
  863. if (c)
  864. line = q + 1;
  865. else
  866. line = q;
  867. /* The '}' will close the @verb command in handle_separator below. */
  868. }
  869. else
  870. {
  871. /* Save the rest of line. */
  872. ELEMENT *e = new_element (ET_raw);
  873. text_append (&e->text, line);
  874. add_to_element_contents (current, e);
  875. debug_nonl ("LINE VERB: %s", line);
  876. retval = GET_A_NEW_LINE; goto funexit; /* Get next line. */
  877. }
  878. } /* CM_verb */
  879. /* Skip empty lines. If we reach the end of input, continue in case there
  880. is an @include. */
  881. /* There are cases when we need more input, but we don't want to
  882. get it in the top-level loop in parse_texi - this is mostly
  883. (always?) when we don't want to start a new, empty line, and
  884. need to get more from the current, incomplete line of input. */
  885. // 3878
  886. while (*line == '\0')
  887. {
  888. static char *allocated_text;
  889. debug ("EMPTY TEXT");
  890. /* Each place we supply Texinfo input we store the supplied
  891. input in a static variable like allocated_text, to prevent
  892. memory leaks. */
  893. free (allocated_text);
  894. line = allocated_text = next_text ();
  895. if (!line)
  896. {
  897. /* TODO: Can this only happen at end of file? */
  898. current = end_line (current);
  899. retval = GET_A_NEW_LINE;
  900. goto funexit;
  901. }
  902. }
  903. if (*line == '@')
  904. {
  905. line_after_command = line + 1;
  906. /* List of single character Texinfo commands. */
  907. if (strchr ("([\"'~@}{,.!?"
  908. " \f\n\r\t"
  909. "*-^`=:|/\\",
  910. *line_after_command))
  911. {
  912. char single_char[2];
  913. single_char[0] = *line_after_command++;
  914. single_char[1] = '\0';
  915. cmd = lookup_command (single_char);
  916. }
  917. else
  918. {
  919. char *command = read_command_name (&line_after_command);
  920. if (command)
  921. {
  922. cmd = lookup_command (command);
  923. if (!cmd)
  924. {
  925. line_error ("unknown command `%s'", command); // 4877
  926. line = line_after_command;
  927. debug ("COMMAND (UNKNOWN) %s", command);
  928. }
  929. }
  930. free (command);
  931. if (!cmd)
  932. {
  933. ELEMENT *paragraph;
  934. // 4226
  935. abort_empty_line (&current, 0);
  936. // 4276
  937. paragraph = begin_paragraph (current);
  938. if (paragraph)
  939. current = paragraph;
  940. //goto funexit;
  941. }
  942. }
  943. if (cmd && (command_data(cmd).flags & CF_ALIAS))
  944. cmd = command_data(cmd).data;
  945. }
  946. /* Handle user-defined macros before anything else because their expansion
  947. may lead to changes in the line. */
  948. if (cmd && (command_data(cmd).flags & CF_MACRO)) // 3894
  949. {
  950. static char *allocated_line;
  951. line = line_after_command;
  952. current = handle_macro (current, &line, cmd);
  953. free (allocated_line);
  954. allocated_line = next_text ();
  955. line = allocated_line;
  956. }
  957. /* 3983 Cases that may "lead to command closing": brace commands that don't
  958. need a brace: accent commands.
  959. @definfoenclose. */
  960. /* This condition is only checked immediately after the command opening,
  961. otherwise the current element is in the 'args' and not right in the
  962. command container. */
  963. else if (command_flags(current) & CF_brace && *line != '{')
  964. {
  965. if (command_with_command_as_argument (current->parent)) // 3988
  966. {
  967. debug ("FOR PARENT @%s command_as_argument @%s",
  968. command_name(current->parent->parent->cmd),
  969. command_name(current->cmd));
  970. if (!current->type)
  971. current->type = ET_command_as_argument;
  972. add_extra_element (current->parent->parent,
  973. "command_as_argument", current);
  974. current = current->parent;
  975. }
  976. else if (command_flags (current) & CF_accent) // 3996 - accent commands
  977. {
  978. if (strchr (whitespace_chars_except_newline, *line))
  979. {
  980. if (isalpha (command_name(current->cmd)[0]))
  981. /* e.g. @dotaccent */
  982. {
  983. char *p; char *s;
  984. KEY_PAIR *k;
  985. p = line + strspn (line, whitespace_chars_except_newline);
  986. k = lookup_extra_key (current, "spaces");
  987. if (!k)
  988. {
  989. asprintf (&s, "%.*s", (int) (p - line), line);
  990. add_extra_string (current, "spaces", s);
  991. }
  992. else
  993. {
  994. asprintf (&s, "%s%.*s",
  995. (char *) k->value,
  996. (int) (p - line), p);
  997. free (k->value);
  998. k->value = (ELEMENT *) s;
  999. }
  1000. line = p;
  1001. }
  1002. else
  1003. {
  1004. line_warn ("accent command `@%s' must not be followed "
  1005. "by whitespace", command_name(current->cmd));
  1006. current = current->parent;
  1007. }
  1008. }
  1009. else if (*line == '@')
  1010. {
  1011. line_error ("use braces to give a command as an argument "
  1012. "to @%s", command_name(current->cmd));
  1013. current = current->parent;
  1014. }
  1015. else if (*line != '\0' && *line != '\n' && *line != '\r')
  1016. {
  1017. ELEMENT *e, *e2;
  1018. debug ("ACCENT");
  1019. e = new_element (ET_following_arg);
  1020. add_to_element_args (current, e);
  1021. e2 = new_element (ET_NONE);
  1022. text_append_n (&e2->text, line, 1);
  1023. add_to_element_contents (e, e2);
  1024. if (current->cmd == CM_dotless
  1025. && *line != 'i' && *line != 'j')
  1026. {
  1027. line_error ("@dotless expects `i' or `j' as argument, "
  1028. "not `%c'", *line);
  1029. }
  1030. if (isalpha (command_name(current->cmd)[0]))
  1031. e->type = ET_space_command_arg;
  1032. while (current->contents.number > 0)
  1033. destroy_element (pop_element_from_contents (current));
  1034. line++;
  1035. current = current->parent;
  1036. }
  1037. else // 4032
  1038. {
  1039. debug ("STRANGE ACC");
  1040. line_warn ("accent command `@%s' must not be followed by "
  1041. "new line", command_name(current->cmd));
  1042. current = current->parent;
  1043. }
  1044. goto funexit;
  1045. }
  1046. else // 4041
  1047. {
  1048. /* TODO: Check 'IGNORE_SPACES_AFTER_BRACED_COMMAND_NAME' config
  1049. variable. */
  1050. if (1)
  1051. {
  1052. char *p;
  1053. p = line + strspn (line, whitespace_chars);
  1054. if (p != line)
  1055. {
  1056. line = p;
  1057. goto funexit;
  1058. }
  1059. }
  1060. line_error ("@%s expected braces",
  1061. command_name(current->cmd));
  1062. current = current->parent;
  1063. }
  1064. }
  1065. else if (handle_menu (&current, &line))
  1066. {
  1067. ; /* Nothing - everything was done in handle_menu. */
  1068. }
  1069. /* line 4161 */
  1070. /* Any other @-command. */
  1071. else if (cmd)
  1072. {
  1073. enum command_id invalid_parent = 0;
  1074. line = line_after_command;
  1075. debug ("COMMAND %s", command_name(cmd));
  1076. /* 4172 @value */
  1077. if (cmd == CM_value)
  1078. {
  1079. char *arg_start;
  1080. line += strspn (line, whitespace_chars);
  1081. if (*line != '{')
  1082. goto value_invalid;
  1083. line++;
  1084. if (!isalnum (*line) && *line != '-' && *line != '_')
  1085. {
  1086. line--;
  1087. goto value_invalid;
  1088. }
  1089. arg_start = line;
  1090. line++;
  1091. line = strpbrk (line,
  1092. " \t\f\r\n" /* whitespace */
  1093. "{\\}~^+\"<>|@"); /* other bytes that aren't allowed */
  1094. if (*line != '}')
  1095. {
  1096. line = arg_start - 1;
  1097. goto value_invalid;
  1098. }
  1099. if (1) /* @value syntax is valid */
  1100. {
  1101. char *value;
  1102. value_valid:
  1103. value = fetch_value (arg_start, line - arg_start);
  1104. if (!value)
  1105. {
  1106. /* Add element for unexpanded @value.
  1107. This is not necessarily an error - in
  1108. Texinfo::Report::gdt we deliberately pass
  1109. in undefined values. */
  1110. ELEMENT *value_elt;
  1111. line_warn ("undefined flag: %.*s", line - arg_start,
  1112. arg_start);
  1113. abort_empty_line (&current, NULL);
  1114. value_elt = new_element (ET_NONE);
  1115. value_elt->cmd = CM_value;
  1116. text_append_n (&value_elt->text, arg_start,
  1117. line - arg_start);
  1118. /* In the Perl code, the name of the flag is stored in
  1119. the "type" field. We need to store in 'text' instead
  1120. and then output it as the type in
  1121. dump_perl.c / api.c. */
  1122. add_to_element_contents (current, value_elt);
  1123. line++; /* past '}' */
  1124. retval = STILL_MORE_TO_PROCESS;
  1125. }
  1126. else
  1127. {
  1128. line++; /* past '}' */
  1129. input_push_text (strdup (line), line_nr.macro);
  1130. input_push_text (strdup (value), 0);
  1131. line += strlen (line);
  1132. retval = STILL_MORE_TO_PROCESS;
  1133. }
  1134. goto funexit;
  1135. }
  1136. else
  1137. {
  1138. value_invalid:
  1139. line_error ("bad syntax for @value");
  1140. retval = STILL_MORE_TO_PROCESS;
  1141. goto funexit;
  1142. }
  1143. }
  1144. /* Warn on deprecated command */
  1145. if (command_data(cmd).flags & CF_deprecated)
  1146. {
  1147. line_warn ("@%s is obsolete.", command_name(cmd));
  1148. }
  1149. /* warn on not appearing at line beginning 4226 */
  1150. // begin line commands 315
  1151. // TODO maybe have a command flag for this
  1152. if (!abort_empty_line (&current, NULL)
  1153. && ((cmd == CM_node || cmd == CM_bye)
  1154. || (command_data(cmd).flags & CF_block)
  1155. || ((command_data(cmd).flags & CF_misc)
  1156. && cmd != CM_comment
  1157. && cmd != CM_c
  1158. && cmd != CM_sp
  1159. && cmd != CM_refill
  1160. && cmd != CM_noindent
  1161. && cmd != CM_indent
  1162. && cmd != CM_columnfractions
  1163. && cmd != CM_tab
  1164. && cmd != CM_item
  1165. && cmd != CM_headitem
  1166. && cmd != CM_verbatiminclude
  1167. && cmd != CM_set
  1168. && cmd != CM_clear
  1169. && cmd != CM_vskip
  1170. && !(command_data(cmd).flags & CF_in_heading))))
  1171. {
  1172. line_warn ("@%s should only appear at the beginning of a line",
  1173. command_name(cmd));
  1174. }
  1175. /* 4233 invalid nestings */
  1176. if (current->parent)
  1177. {
  1178. /* Check whether outer command can contain cmd. Commands are
  1179. classified according to what commands they can contain:
  1180. accents
  1181. full text
  1182. simple text
  1183. full line
  1184. full line no refs
  1185. */
  1186. int ok = 0; /* Whether nesting is allowed. */
  1187. /* Whether command is a "simple text" command. Use a variable
  1188. to avoid repeating a complex conditional. */
  1189. int simple_text_command = 0;
  1190. enum command_id outer = current->parent->cmd;
  1191. unsigned long outer_flags = command_data(outer).flags;
  1192. unsigned long cmd_flags = command_data(cmd).flags;
  1193. // much TODO here.
  1194. /* 409 "simple text commands" */
  1195. if ((outer_flags & CF_misc
  1196. && (command_data(outer).data >= 0
  1197. || (command_data(outer).data == MISC_line
  1198. && !(outer_flags & (CF_def | CF_sectioning)))
  1199. || command_data(outer).data == MISC_text)
  1200. && outer != CM_center
  1201. && outer != CM_exdent) // 423
  1202. || outer == CM_titlefont // 425
  1203. || outer == CM_anchor
  1204. || outer == CM_xref
  1205. || outer == CM_ref
  1206. || outer == CM_pxref
  1207. || outer == CM_inforef
  1208. || outer == CM_shortcaption
  1209. || outer == CM_math
  1210. || outer == CM_indicateurl
  1211. || outer == CM_email
  1212. || outer == CM_uref
  1213. || outer == CM_url
  1214. || outer == CM_image
  1215. || outer == CM_abbr
  1216. || outer == CM_acronym
  1217. || outer == CM_dmn
  1218. || (outer_flags & CF_index_entry_command) // 563
  1219. || (outer_flags & CF_block // 475
  1220. && !(outer_flags & CF_def)
  1221. && command_data(outer).data != BLOCK_raw
  1222. && command_data(outer).data != BLOCK_conditional))
  1223. {
  1224. simple_text_command = 1;
  1225. }
  1226. if (outer_flags & CF_root && current->type != ET_misc_line_arg)
  1227. ok = 1; // 4242
  1228. else if (outer_flags & CF_block
  1229. && current->type != ET_block_line_arg)
  1230. ok = 1; // 4247
  1231. else if ((outer == CM_item
  1232. || outer == CM_itemx)
  1233. && current->type != ET_misc_line_arg)
  1234. ok = 1; // 4252
  1235. else if (outer_flags & CF_accent) // 358
  1236. {
  1237. if (cmd_flags & (CF_nobrace | CF_accent))
  1238. ok = 1;
  1239. else if (cmd_flags & CF_brace
  1240. && command_data(cmd).data == 0)
  1241. ok = 1; /* glyph command */
  1242. if (cmd == CM_c || cmd == CM_comment)
  1243. ok = 1;
  1244. }
  1245. else if (outer == CM_ctrl
  1246. || outer == CM_errormsg)
  1247. {
  1248. ok = 0;
  1249. }
  1250. // 432 "full text commands"
  1251. else if ((outer_flags & CF_brace
  1252. && ((outer_flags & CF_inline)
  1253. || command_data(outer).data == BRACE_style))
  1254. // 445 "full line commands"
  1255. || outer == CM_center
  1256. || outer == CM_exdent
  1257. || outer == CM_item
  1258. || outer == CM_itemx
  1259. || (!current->parent->cmd && current_context () == ct_def)
  1260. // 420 "full line no refs commands"
  1261. || (outer_flags & (CF_sectioning | CF_def))
  1262. // 4261
  1263. || (!current->parent->cmd && current_context () == ct_def)
  1264. // 409 "simple text commands"
  1265. || simple_text_command)
  1266. {
  1267. // "in full text commands".
  1268. if (cmd_flags & CF_nobrace) // 370
  1269. ok = 1;
  1270. if (cmd_flags & CF_brace && !(cmd_flags & CF_INFOENCLOSE)) // 370
  1271. ok = 1;
  1272. else if (cmd == CM_c
  1273. || cmd == CM_comment
  1274. || cmd == CM_refill
  1275. || cmd == CM_noindent
  1276. || cmd == CM_indent
  1277. || cmd == CM_columnfractions
  1278. || cmd == CM_set
  1279. || cmd == CM_clear
  1280. || cmd == CM_end) // 373
  1281. ok = 1;
  1282. else if (cmd_flags & CF_format_raw)
  1283. ok = 1; // 379
  1284. if (cmd == CM_caption || cmd == CM_shortcaption)
  1285. ok = 0; // 381
  1286. if (cmd_flags & CF_block
  1287. && command_data(cmd).data == BLOCK_conditional)
  1288. ok = 1; // 384
  1289. // 390 exceptions for all of "full line commands",
  1290. // "full line commands no refs" and "simple text commands"
  1291. if (!(outer_flags & CF_brace
  1292. && (command_data(outer).data == 1)))
  1293. {
  1294. if (cmd == CM_indent || cmd == CM_noindent)
  1295. ok = 0;
  1296. }
  1297. // 396 exceptions for "full line no refs" and "simple text"
  1298. if (outer_flags & (CF_sectioning | CF_def)
  1299. // 4261
  1300. || (!current->parent->cmd && current_context () == ct_def)
  1301. || simple_text_command)
  1302. {
  1303. if (cmd == CM_titlefont
  1304. || cmd == CM_anchor
  1305. || cmd == CM_footnote
  1306. || cmd == CM_verb
  1307. || cmd == CM_indent || cmd == CM_noindent)
  1308. ok = 0;
  1309. }
  1310. // 405 exceptions for "simple text commands" only
  1311. if (simple_text_command)
  1312. {
  1313. if (cmd == CM_xref
  1314. || cmd == CM_ref
  1315. || cmd == CM_pxref
  1316. || cmd == CM_inforef) // 404
  1317. ok = 0;
  1318. }
  1319. }
  1320. else
  1321. {
  1322. /* Default to valid nesting, for example for commands for which
  1323. it is not defined which commands can occur within them (e.g.
  1324. @tab?). */
  1325. ok = 1;
  1326. }
  1327. if (!ok)
  1328. {
  1329. invalid_parent = current->parent->cmd;
  1330. if (!invalid_parent)
  1331. {
  1332. /* current_context () == ct_def. Find def block containing
  1333. command. 4258 */
  1334. ELEMENT *d = current;
  1335. while (d->parent
  1336. && d->parent->type != ET_def_line)
  1337. d = d->parent;
  1338. invalid_parent = d->parent->parent->cmd;
  1339. }
  1340. }
  1341. }
  1342. /* 4274 */
  1343. if (current_context () == ct_def && cmd == CM_NEWLINE)
  1344. {
  1345. retval = GET_A_NEW_LINE;
  1346. goto funexit;
  1347. }
  1348. /* 4276 check command doesn't start a paragraph */
  1349. /* TODO store this in cmd->flags. Or better, change the meaning
  1350. of CF_misc. */
  1351. if (!(command_data(cmd).flags & (CF_misc | CF_block)
  1352. || cmd == CM_titlefont
  1353. || cmd == CM_caption
  1354. || cmd == CM_shortcaption
  1355. || cmd == CM_image
  1356. || cmd == CM_ASTERISK /* @* */
  1357. || cmd == CM_hyphenation
  1358. || cmd == CM_anchor
  1359. || cmd == CM_errormsg
  1360. || (command_data(cmd).flags & CF_index_entry_command)))
  1361. {
  1362. /*
  1363. Unless no paragraph commands (line 311):
  1364. All misc commands
  1365. All block commands
  1366. 'titlefont', 'caption', 'shortcaption',
  1367. 'image', '*', 'hyphenation', 'anchor', 'errormsg'
  1368. Index commands
  1369. */
  1370. ELEMENT *paragraph;
  1371. paragraph = begin_paragraph (current);
  1372. if (paragraph)
  1373. current = paragraph;
  1374. }
  1375. // 4281
  1376. if (cmd != 0)
  1377. {
  1378. if (close_paragraph_command (cmd))
  1379. current = end_paragraph (current, 0, 0);
  1380. if (close_preformatted_command (cmd))
  1381. current = end_preformatted (current, 0, 0);
  1382. }
  1383. if (cmd == 0)
  1384. {
  1385. // 4287 Unknown command
  1386. retval = 1;
  1387. goto funexit;
  1388. }
  1389. /* line 4289 */
  1390. /* the 'misc-commands' - no braces and not block commands (includes
  1391. @end). Mostly taking a line argument, except for a small number
  1392. of exceptions, like @tab. */
  1393. else if (command_data(cmd).flags & CF_misc)
  1394. {
  1395. int status;
  1396. current = handle_misc_command (current, &line, cmd, &status,
  1397. invalid_parent);
  1398. if (status == 1)
  1399. {
  1400. retval = GET_A_NEW_LINE;
  1401. goto funexit;
  1402. }
  1403. else if (status == 2)
  1404. {
  1405. retval = FINISHED_TOTALLY;
  1406. goto funexit;
  1407. }
  1408. }
  1409. /* line 4632 */
  1410. else if (command_data(cmd).flags & CF_block)
  1411. {
  1412. int new_line = 0;
  1413. current = handle_block_command (current, &line, cmd, &new_line,
  1414. invalid_parent);
  1415. if (new_line)
  1416. {
  1417. /* For @macro, to get a new line. This is done instead of
  1418. doing the EMPTY TEXT (3879) code on the next time round. */
  1419. retval = GET_A_NEW_LINE; goto funexit;
  1420. }
  1421. }
  1422. else if (command_data(cmd).flags & CF_brace
  1423. || command_data(cmd).flags & CF_accent) /* line 4835 */
  1424. {
  1425. current = handle_brace_command (current, &line,
  1426. cmd, invalid_parent);
  1427. }
  1428. /* No-brace command */
  1429. else if (command_data(cmd).flags & CF_nobrace) /* 4864 */
  1430. {
  1431. ELEMENT *nobrace;
  1432. nobrace = new_element (ET_NONE);
  1433. nobrace->cmd = cmd;
  1434. add_to_element_contents (current, nobrace);
  1435. if (cmd == CM_BACKSLASH && current_context () != ct_math)
  1436. {
  1437. line_warn ("@\\ should only appear in math context");
  1438. }
  1439. if (cmd == CM_NEWLINE)
  1440. {
  1441. current = end_line (current);
  1442. retval = GET_A_NEW_LINE;
  1443. goto funexit;
  1444. }
  1445. }
  1446. #if 0
  1447. else
  1448. {
  1449. /* error: unknown command */
  1450. }
  1451. #endif
  1452. }
  1453. /* "Separator" - line 4881 */
  1454. else if (*line != '\0' && strchr ("{}@,:\t.\f", *line))
  1455. {
  1456. char separator = *line++;
  1457. debug ("SEPARATOR: %c", separator);
  1458. if (separator == '@')
  1459. line_error ("unexpected @");
  1460. else
  1461. current = handle_separator (current, separator, &line);
  1462. } /* 5326 */
  1463. /* "Misc text except end of line." */
  1464. else if (*line && *line != '\n') /* 5326 */
  1465. {
  1466. size_t len;
  1467. /* Output until next command, separator or newline. */
  1468. {
  1469. char saved; /* TODO: Have a length argument to merge_text? */
  1470. len = strcspn (line, "{}@,:\t.\n\f");
  1471. saved = line[len];
  1472. line[len] = '\0';
  1473. current = merge_text (current, line);
  1474. line += len;
  1475. *line = saved;
  1476. }
  1477. retval = 1;
  1478. goto funexit;
  1479. }
  1480. else /* 5331 End of line */
  1481. {
  1482. if (current->type)
  1483. debug ("END LINE (%s)", element_type_names[current->type]);
  1484. else if (current->cmd)
  1485. debug ("END LINE (@%s)", command_name(current->cmd));
  1486. else
  1487. debug ("END LINE");
  1488. if (current->parent)
  1489. {
  1490. debug_nonl (" <- ");
  1491. if (current->parent->cmd)
  1492. debug_nonl("@%s", command_name(current->parent->cmd));
  1493. if (current->parent->type)
  1494. debug_nonl("(%s)", element_type_names[current->parent->type]);
  1495. debug ("");
  1496. debug ("");
  1497. }
  1498. if (*line == '\n')
  1499. {
  1500. current = merge_text (current, "\n");
  1501. line++;
  1502. }
  1503. else
  1504. ;//abort ();
  1505. /* '@end' is processed in here. */
  1506. current = end_line (current); /* 5344 */
  1507. retval = GET_A_NEW_LINE;
  1508. }
  1509. funexit:
  1510. *current_inout = current;
  1511. *line_inout = line;
  1512. return retval;
  1513. }
  1514. /* Pass in and return root of a "Texinfo tree". */
  1515. /* 3676 */
  1516. ELEMENT *
  1517. parse_texi (ELEMENT *root_elt)
  1518. {
  1519. ELEMENT *current = root_elt;
  1520. char *allocated_line = 0, *line;
  1521. /* Read input file line-by-line. */
  1522. while (1)
  1523. {
  1524. free (allocated_line);
  1525. line = allocated_line = next_text ();
  1526. if (!allocated_line)
  1527. break; /* Out of input. */
  1528. debug_nonl ("NEW LINE %s", line);
  1529. // 3706
  1530. /* If not in 'raw' or 'conditional' and parent isn't a 'verb', collect
  1531. leading whitespace and save as an "ET_empty_line" element. This
  1532. element type can be changed in 'abort_empty_line' when more text is
  1533. read. */
  1534. if (!((command_flags(current) & CF_block)
  1535. && (command_data(current->cmd).data == BLOCK_raw
  1536. || command_data(current->cmd).data == BLOCK_conditional)
  1537. || current->parent && current->parent->cmd == CM_verb)
  1538. && current_context () != ct_def)
  1539. {
  1540. ELEMENT *e;
  1541. int n;
  1542. debug ("BEGIN LINE");
  1543. e = new_element (ET_empty_line);
  1544. add_to_element_contents (current, e);
  1545. n = strspn (line, whitespace_chars_except_newline);
  1546. text_append_n (&e->text, line, n);
  1547. line += n;
  1548. }
  1549. /* Process from start of remaining line, advancing it until we run out
  1550. of line. */
  1551. while (1)
  1552. {
  1553. int status = process_remaining_on_line (&current, &line);
  1554. if (status == GET_A_NEW_LINE)
  1555. break;
  1556. if (status == FINISHED_TOTALLY)
  1557. goto finished_totally;
  1558. if (!line)
  1559. break;
  1560. }
  1561. }
  1562. finished_totally:
  1563. /* Check for unclosed conditionals */
  1564. while (conditional_number > 0)
  1565. {
  1566. line_error ("expected @end %s",
  1567. command_name(conditional_stack[conditional_number - 1]));
  1568. conditional_number--;
  1569. }
  1570. {
  1571. ELEMENT *dummy; // 5254
  1572. current = close_commands (current, CM_NONE, &dummy, CM_NONE);
  1573. /* Make sure we are at the very top - we could have stopped at the "top"
  1574. element, with "document_root" still to go. (This happens if the file
  1575. didn't end with "@bye".) */
  1576. while (current->parent)
  1577. current = current->parent;
  1578. }
  1579. /* Check for "unclosed stacks". */
  1580. return current;
  1581. } /* 5372 */
  1582. /* 5793 - end of code in Parser.pm */