PageRenderTime 58ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/diss/tags/finalsubmission/src/compiler/tools/NccPostProcessor.java

http://thesandbox.googlecode.com/
Java | 1506 lines | 1039 code | 43 blank | 424 comment | 184 complexity | 16ae82511d5dbe8101c603e31ec7241b MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. package compiler.tools;
  2. import java.io.File;
  3. import java.io.FileReader;
  4. import java.io.IOException;
  5. import java.io.LineNumberReader;
  6. import java.util.ArrayList;
  7. import java.util.HashSet;
  8. import java.util.StringTokenizer;
  9. /**
  10. * This class performs the post processing jobs collected during normal parsing.
  11. *
  12. * @author Richard Hill
  13. */
  14. public class NccPostProcessor
  15. {
  16. private CommandLineOptions clo;
  17. private File readFrom;
  18. private NccSourceHandler sh;
  19. private enum Types {DO, DOWHILE, ELSE, FOR, IF, SWITCH, WHILE, GETCHAR, PUTCHAR, PRINTF, SCANF, NOVALUE};
  20. //Valid printf end formatters
  21. private HashSet<String> validPrintfEnds = new HashSet<String>();
  22. //Valid printf middle chars
  23. private HashSet<String> validPrintfMids = new HashSet<String>();
  24. //Valid scanf end formatters
  25. private HashSet<String> validScanfEnds = new HashSet<String>();
  26. //Valid scanf middle chars
  27. private HashSet<String> validScanfMids = new HashSet<String>();
  28. /**
  29. * Constructor.
  30. *
  31. * @param clo The command line options data structure.
  32. */
  33. public NccPostProcessor(CommandLineOptions clo)
  34. {
  35. this.clo = clo;
  36. readFrom = new File(clo.fName);
  37. sh = new NccSourceHandler(clo.fName);
  38. initValidPrintfEnds();
  39. initValidPrintfMids();
  40. initValidScanfEnds();
  41. initValidScanfMids();
  42. }
  43. /**
  44. * This method looks at the job and decides how to process it.
  45. *
  46. * @return The NccError generated if there is one, null otherwise.
  47. */
  48. public NccError processJob(NccPostProcessorJob j)
  49. {
  50. switch(toType(j.getJobType())){
  51. case DO : return matchDo(j.getBeginLine());
  52. case DOWHILE: return null; //see below
  53. case ELSE : return matchElse(j.getBeginLine());
  54. case FOR : return matchFor(j.getBeginLine());
  55. case IF : return matchIf(j.getBeginLine());
  56. case SWITCH : return matchSwitch(j.getBeginLine());
  57. case WHILE : return matchWhile(j.getBeginLine());
  58. case GETCHAR: return checkGetchar(j);
  59. case PUTCHAR: return checkPutchar(j);
  60. case PRINTF : return checkPrintf(j);
  61. case SCANF : return checkScanf(j);
  62. default : return null;
  63. }
  64. }
  65. /**
  66. * NCC Error NCC Error Number(s): 115 (Print Regardless)
  67. *
  68. * Matches a 'do'. e.g.
  69. *
  70. * //DO-WHILE
  71. * do{
  72. * y++;
  73. * }while(x-- > 0);
  74. *
  75. * @param beginLine The line the matching process begins on.
  76. * @return The NccError generated if there is one, null
  77. * otherwise.
  78. */
  79. private NccError matchDo(int beginLine)
  80. {
  81. NccError err = null;
  82. //System.err.println("Matching do");
  83. try{
  84. FileReader fr = new FileReader(readFrom);
  85. LineNumberReader lnr = new LineNumberReader(fr);
  86. //Stop the file one line before the line we're interested in
  87. while(lnr.getLineNumber() < beginLine - 1){
  88. //System.err.println(lnr.readLine());
  89. lnr.readLine();
  90. }
  91. //Now read character by character
  92. int i;
  93. int counter = 0;
  94. while( (i = lnr.read()) != -1){ //While we're not at the end of the file
  95. counter++;
  96. if(i == (int) 'd'){
  97. counter--;
  98. //System.err.println("Matched a 'd' in 'do'");
  99. //Matched a 'd', move on to find an 'o'
  100. i = lnr.read();
  101. if(i == (int) 'o'){
  102. //System.err.println("Matched an 'o' in 'do'");
  103. i = lnr.read();
  104. /*
  105. * Most of the time this should be a '{', on the off
  106. * chance that it is not advance the input through
  107. * whitespace and comments.
  108. */
  109. boolean keepMoving = true;
  110. while(keepMoving){
  111. if(Character.isWhitespace((char)i)){
  112. i = lnr.read(); //Advance
  113. }
  114. else if(i == (int) '/'){
  115. //parsing comment
  116. i = matchComment(lnr);
  117. }
  118. else if(i == (int) '{'){
  119. //Correct usage of { ensured.
  120. //System.err.println("Complete & Correct!");
  121. return null;
  122. }
  123. else{
  124. keepMoving = false;
  125. }
  126. }
  127. //If we reach here then { was not used correctly so a warning is required
  128. if(clo.dFlag){
  129. err = new NccError(beginLine, 115);
  130. err.addTextln("Warning: Line " + beginLine + ": Poor block conversion after 'do'.");
  131. err.addTextln("\t" + sh.getLineNumber(beginLine));
  132. err.addTextln("\t" + sh.generateWhiteSpace(counter, beginLine) + "^");
  133. err.addTextln("DIAGNOSIS: The statement(s) in the 'do' section of the " +
  134. "do-while loop beginning on line " + beginLine + " are not enclosed by " +
  135. "curly brackets, this may result in code ambiguity.");
  136. err.addText("See NCC Error Code 115 for more details");
  137. }
  138. break; //Matched entire 'do{' so break from while and return
  139. }
  140. }
  141. }
  142. lnr.close();
  143. fr.close();
  144. }
  145. catch(IOException e){
  146. System.out.println("IOException: " + e.getMessage());
  147. e.printStackTrace();
  148. }
  149. return err;
  150. }
  151. /*
  152. * This method would match the while segment of a 'do-while'. e.g.
  153. *
  154. * //DO-WHILE
  155. * do{
  156. * y++;
  157. * }while(x-- > 0);
  158. *
  159. * But as there is not block convention to encourage the correct use of and
  160. * because any syntax errors should have been reported by the parser we
  161. * don't need to perform any checks so we just return null here.
  162. *
  163. * @param beginLine The line the matching process begins on.
  164. * @return The NccError generated if there is one, null
  165. * otherwise.
  166. *
  167. * private NccError mactchDoWhile(int beginLine)
  168. * {
  169. * return null;
  170. * }
  171. */
  172. /**
  173. * NCC Error NCC Error Number(s): 116 (Print Regardless)
  174. *
  175. * Matches an 'else'.
  176. *
  177. * @param beginLine The line the matching process begins on.
  178. * @return The NccError generated if there is one, null
  179. * otherwise.
  180. */
  181. private NccError matchElse(int beginLine)
  182. {
  183. NccError err = null;
  184. //System.err.println("Matching else");
  185. try{
  186. FileReader fr = new FileReader(readFrom);
  187. LineNumberReader lnr = new LineNumberReader(fr);
  188. //Stop the file one line before the line we're interested in
  189. while(lnr.getLineNumber() < beginLine - 1){
  190. //System.err.println(lnr.readLine());
  191. lnr.readLine();
  192. }
  193. //Now read character by character
  194. int i;
  195. int counter = 0;
  196. while( (i = lnr.read()) != -1){ //While we're not at the end of the file
  197. counter++;
  198. if(i == (int) 'e'){
  199. counter--;
  200. //System.err.println("Matched an 'e' in 'else'");
  201. //Matched an 'e', move on to find an 'l'
  202. i = lnr.read();
  203. if(i == (int) 'l'){
  204. //System.err.println("Matched an 'l' in 'else'");
  205. //Matched a 'l', move on to find an 's'
  206. i = lnr.read();
  207. if(i == (int) 's'){
  208. //System.err.println("Matched an 's' in 'else'");
  209. //Matched a 's', move on to find an 'e'
  210. i = lnr.read();
  211. if(i == (int) 'e'){
  212. //System.err.println("Matched an 'e' in 'else'");
  213. i = lnr.read();
  214. /*
  215. * Most of the time this should be a '{', on the off
  216. * chance that it is not advance the input through
  217. * whitespace and comments.
  218. */
  219. boolean keepMoving = true;
  220. while(keepMoving){
  221. if(Character.isWhitespace((char)i)){
  222. i = lnr.read(); //Advance
  223. }
  224. else if(i == (int) '/'){
  225. //parsing comment
  226. i = matchComment(lnr);
  227. }
  228. else if(i == (int) '{'){
  229. //Correct usage of { ensured.
  230. //System.err.println("Complete & Correct!");
  231. return null;
  232. }
  233. else{
  234. keepMoving = false;
  235. }
  236. }
  237. //If we reach here then { was not used correctly so a warning is required
  238. if(clo.dFlag){
  239. err = new NccError(beginLine, 116);
  240. err.addTextln("Warning: Line " + beginLine + ": Poor block conversion after 'else'.");
  241. err.addTextln("\t" + sh.getLineNumber(beginLine));
  242. err.addTextln("\t" + sh.generateWhiteSpace(counter, beginLine) + "^");
  243. err.addTextln("DIAGNOSIS: The statement(s) in the 'else' section of the " +
  244. "if-else control statement beginning on line " + beginLine + " are not enclosed by " +
  245. "curly brackets, this may result in code ambiguity.");
  246. err.addText("See NCC Error Code 116 for more details");
  247. }
  248. break; //Matched entire 'else{' so break from while and return
  249. }
  250. }
  251. }
  252. }
  253. }
  254. lnr.close();
  255. fr.close();
  256. }
  257. catch(IOException e){
  258. System.out.println("IOException: " + e.getMessage());
  259. e.printStackTrace();
  260. }
  261. return err;
  262. }
  263. /**
  264. * NCC Error NCC Error Number(s): 117 (Print Regardless)
  265. *
  266. * Matches a 'for'.
  267. *
  268. * @param beginLine The line the matching process begins on.
  269. * @return The NccError generated if there is one, null
  270. * otherwise.
  271. */
  272. private NccError matchFor(int beginLine)
  273. {
  274. NccError err = null;
  275. //System.err.println("Matching for");
  276. try{
  277. FileReader fr = new FileReader(readFrom);
  278. LineNumberReader lnr = new LineNumberReader(fr);
  279. //Stop the file one line before the line we're interested in
  280. while(lnr.getLineNumber() < beginLine - 1){
  281. //System.err.println(lnr.readLine());
  282. lnr.readLine();
  283. }
  284. //Now read character by character
  285. int i;
  286. int counter = 0;
  287. while( (i = lnr.read()) != -1){ //While we're not at the end of the file
  288. counter++;
  289. if(i == (int) 'f'){
  290. counter--;
  291. //System.err.println("Matched an 'f' in 'for'");
  292. //Matched an 'f', move on to find an 'o'
  293. i = lnr.read();
  294. if(i == (int) 'o'){
  295. //System.err.println("Matched an 'o' in 'for'");
  296. //Matched an 'o', move on to find an 'r'
  297. i = lnr.read();
  298. if(i == (int) 'r'){
  299. //System.err.println("Matched an 'r' in 'for'");
  300. i = lnr.read();
  301. /*
  302. * Most of the time this should be a '(', on the off
  303. * chance that it is not advance the input through
  304. * whitespace and comments.
  305. */
  306. boolean keepMoving = true;
  307. while(keepMoving){
  308. if(Character.isWhitespace((char)i)){
  309. i = lnr.read(); //Advance
  310. }
  311. else if(i == (int) '/'){
  312. //parsing comment
  313. i = matchComment(lnr);
  314. }
  315. else if(i == (int) '('){
  316. i = matchBrackets(lnr);
  317. }
  318. else{
  319. keepMoving = false;
  320. }
  321. }
  322. /*
  323. * Most of the time this should be a '{', on the off
  324. * chance that it is not advance the input through
  325. * whitespace and comments.
  326. */
  327. keepMoving = true;
  328. while(keepMoving){
  329. if(Character.isWhitespace((char)i)){
  330. i = lnr.read(); //Advance
  331. }
  332. else if(i == (int) '/'){
  333. //parsing comment
  334. i = matchComment(lnr);
  335. }
  336. else if(i == (int) '{'){
  337. //Correct usage of { ensured.
  338. //System.err.println("Complete & Correct!");
  339. return null;
  340. }
  341. else{
  342. keepMoving = false;
  343. }
  344. }
  345. //If we reach here then { was not used correctly so a warning is required
  346. if(clo.dFlag){
  347. err = new NccError(beginLine, 117);
  348. err.addTextln("Warning: Line " + beginLine + ": Poor block conversion after 'for'.");
  349. err.addTextln("\t" + sh.getLineNumber(beginLine));
  350. err.addTextln("\t" + sh.generateWhiteSpace(counter, beginLine) + "^");
  351. err.addTextln("DIAGNOSIS: The statement(s) in the 'for' section of the " +
  352. "for control statement beginning on line " + beginLine + " are not enclosed by " +
  353. "curly brackets, this may result in code ambiguity.");
  354. err.addText("See NCC Error Code 117 for more details");
  355. }
  356. break; //Matched entire 'for{' so break from while and return
  357. }
  358. }
  359. }
  360. }
  361. lnr.close();
  362. fr.close();
  363. }
  364. catch(IOException e){
  365. System.out.println("IOException: " + e.getMessage());
  366. e.printStackTrace();
  367. }
  368. return err;
  369. }
  370. /**
  371. * NCC Error NCC Error Number(s): 118 (Print Regardless)
  372. *
  373. * Matches an 'if'.
  374. *
  375. * @param beginLine The line the matching process begins on.
  376. * @return The NccError generated if there is one, null
  377. * otherwise.
  378. */
  379. private NccError matchIf(int beginLine)
  380. {
  381. NccError err = null;
  382. //System.err.println("Matching if");
  383. try{
  384. FileReader fr = new FileReader(readFrom);
  385. LineNumberReader lnr = new LineNumberReader(fr);
  386. //Stop the file one line before the line we're interested in
  387. while(lnr.getLineNumber() < beginLine - 1){
  388. //System.err.println(lnr.readLine());
  389. lnr.readLine();
  390. }
  391. //Now read character by character
  392. int i;
  393. int counter = 0;
  394. while( (i = lnr.read()) != -1){ //While we're not at the end of the file
  395. counter++;
  396. if(i == (int) 'i'){
  397. counter--;
  398. //System.err.println("Matched an 'i' in 'if'");
  399. //Matched an 'i', move on to find an 'f'
  400. i = lnr.read();
  401. if(i == (int) 'f'){
  402. //System.err.println("Matched an 'f' in 'if'");
  403. i = lnr.read();
  404. /*
  405. * Most of the time this should be a '(', on the off
  406. * chance that it is not advance the input through
  407. * whitespace and comments.
  408. */
  409. boolean keepMoving = true;
  410. while(keepMoving){
  411. if(Character.isWhitespace((char)i)){
  412. i = lnr.read(); //Advance
  413. }
  414. else if(i == (int) '/'){
  415. //parsing comment
  416. i = matchComment(lnr);
  417. }
  418. else if(i == (int) '('){
  419. i = matchBrackets(lnr);
  420. }
  421. else{
  422. keepMoving = false;
  423. }
  424. }
  425. /*
  426. * Most of the time this should be a '{', on the off
  427. * chance that it is not advance the input through
  428. * whitespace and comments.
  429. */
  430. keepMoving = true;
  431. while(keepMoving){
  432. if(Character.isWhitespace((char)i)){
  433. i = lnr.read(); //Advance
  434. }
  435. else if(i == (int) '/'){
  436. //parsing comment
  437. i = matchComment(lnr);
  438. }
  439. else if(i == (int) '{'){
  440. //Correct usage of { ensured.
  441. //System.err.println("Complete & Correct!");
  442. return null;
  443. }
  444. else{
  445. keepMoving = false;
  446. }
  447. }
  448. //If we reach here then { was not used correctly so a warning is required
  449. if(clo.dFlag){
  450. err = new NccError(beginLine, 118);
  451. err.addTextln("Warning: Line " + beginLine + ": Poor block conversion after 'if'.");
  452. err.addTextln("\t" + sh.getLineNumber(beginLine));
  453. err.addTextln("\t" + sh.generateWhiteSpace(counter, beginLine) + "^");
  454. err.addTextln("DIAGNOSIS: The statement(s) in the 'if' section of the " +
  455. "if control statement beginning on line " + beginLine + " are not enclosed by " +
  456. "curly brackets, this may result in code ambiguity.");
  457. err.addText("See NCC Error Code 118 for more details");
  458. }
  459. break; //Matched entire 'if{' so break from while and return
  460. }
  461. }
  462. }
  463. lnr.close();
  464. fr.close();
  465. }
  466. catch(IOException e){
  467. System.out.println("IOException: " + e.getMessage());
  468. e.printStackTrace();
  469. }
  470. return err;
  471. }
  472. /**
  473. * NCC Error NCC Error Number(s): 119 (Print Regardless)
  474. *
  475. * Matches a 'switch'.
  476. *
  477. * @param beginLine The line the matching process begins on.
  478. * @return The NccError generated if there is one, null
  479. * otherwise.
  480. */
  481. private NccError matchSwitch(int beginLine)
  482. {
  483. NccError err = null;
  484. //System.err.println("Matching switch");
  485. try{
  486. FileReader fr = new FileReader(readFrom);
  487. LineNumberReader lnr = new LineNumberReader(fr);
  488. //Stop the file one line before the line we're interested in
  489. while(lnr.getLineNumber() < beginLine - 1){
  490. //System.err.println(lnr.readLine());
  491. lnr.readLine();
  492. }
  493. //Now read character by character
  494. int i;
  495. int counter = 0;
  496. while( (i = lnr.read()) != -1){ //While we're not at the end of the file
  497. counter++;
  498. if(i == (int) 's'){
  499. counter--;
  500. //System.err.println("Matched an 's' in 'switch'");
  501. //Matched an 's', move on to find a 'w'
  502. i = lnr.read();
  503. if(i == (int) 'w'){
  504. //System.err.println("Matched a 'w' in 'switch'");
  505. //Matched a 'w', move on to find an 'i'
  506. i = lnr.read();
  507. if(i == (int) 'i'){
  508. //System.err.println("Matched an 'i' in 'switch'");
  509. //Matched an 'i', move on to find a 't'
  510. i = lnr.read();
  511. if(i == (int) 't'){
  512. //System.err.println("Matched a 't' in 'switch'");
  513. //Matched an 't', move on to find a 'c'
  514. i = lnr.read();
  515. if(i == (int) 'c'){
  516. //System.err.println("Matched a 'c' in 'switch'");
  517. //Matched a 'c', move on to find an 'h'
  518. i = lnr.read();
  519. if(i == (int) 'h'){
  520. //System.err.println("Matched an 'h' in 'switch'");
  521. i = lnr.read();
  522. /*
  523. * Most of the time this should be a '(', on the off
  524. * chance that it is not advance the input through
  525. * whitespace and comments.
  526. */
  527. boolean keepMoving = true;
  528. while(keepMoving){
  529. if(Character.isWhitespace((char)i)){
  530. i = lnr.read(); //Advance
  531. }
  532. else if(i == (int) '/'){
  533. //parsing comment
  534. i = matchComment(lnr);
  535. }
  536. else if(i == (int) '('){
  537. i = matchBrackets(lnr);
  538. }
  539. else{
  540. keepMoving = false;
  541. }
  542. }
  543. /*
  544. * Most of the time this should be a '{', on the off
  545. * chance that it is not advance the input through
  546. * whitespace and comments.
  547. */
  548. keepMoving = true;
  549. while(keepMoving){
  550. if(Character.isWhitespace((char)i)){
  551. i = lnr.read(); //Advance
  552. }
  553. else if(i == (int) '/'){
  554. //parsing comment
  555. i = matchComment(lnr);
  556. }
  557. else if(i == (int) '{'){
  558. //Correct usage of { ensured.
  559. //System.err.println("Complete & Correct!");
  560. return null;
  561. }
  562. else{
  563. keepMoving = false;
  564. }
  565. }
  566. //If we reach here then { was not used correctly so a warning is required
  567. if(clo.dFlag){
  568. err = new NccError(beginLine, 119);
  569. err.addTextln("Warning: Line " + beginLine + ": Poor block conversion after 'switch'.");
  570. err.addTextln("\t" + sh.getLineNumber(beginLine));
  571. err.addTextln("\t" + sh.generateWhiteSpace(counter, beginLine) + "^");
  572. err.addTextln("DIAGNOSIS: The case statement(s) in the options section of the " +
  573. "'switch' control statement beginning on line " + beginLine + " are not enclosed by " +
  574. "curly brackets, this may result in code ambiguity.");
  575. err.addText("See NCC Error Code 119 for more details");
  576. }
  577. break; //Matched entire 'switch{' so break from while and return
  578. }
  579. }
  580. }
  581. }
  582. }
  583. }
  584. }
  585. lnr.close();
  586. fr.close();
  587. }
  588. catch(IOException e){
  589. System.out.println("IOException: " + e.getMessage());
  590. e.printStackTrace();
  591. }
  592. return err;
  593. }
  594. /**
  595. * NCC Error NCC Error Number(s): 120 (Print Regardless)
  596. *
  597. * Matches a 'while'.
  598. *
  599. * @param beginLine The line the matching process begins on.
  600. * @return The NccError generated if there is one, null
  601. * otherwise.
  602. */
  603. private NccError matchWhile(int beginLine)
  604. {
  605. NccError err = null;
  606. //System.err.println("Matching while");
  607. try{
  608. FileReader fr = new FileReader(readFrom);
  609. LineNumberReader lnr = new LineNumberReader(fr);
  610. //Stop the file one line before the line we're interested in
  611. while(lnr.getLineNumber() < beginLine - 1){
  612. //System.err.println(lnr.readLine());
  613. lnr.readLine();
  614. }
  615. //Now read character by character
  616. int i;
  617. int counter = 0;
  618. while( (i = lnr.read()) != -1){ //While we're not at the end of the file
  619. counter++;
  620. if(i == (int) 'w'){
  621. counter--;
  622. //System.err.println("Matched a 'w' in 'while'");
  623. //Matched an 'w', move on to find an 'h'
  624. i = lnr.read();
  625. if(i == (int) 'h'){
  626. //System.err.println("Matched an 'h' in 'while'");
  627. //Matched an 'h', move on to find an 'i'
  628. i = lnr.read();
  629. if(i == (int) 'i'){
  630. //System.err.println("Matched an 'i' in 'while'");
  631. //Matched an 'i', move on to find an 'l'
  632. i = lnr.read();
  633. if(i == (int) 'l'){
  634. //System.err.println("Matched an 'l' in 'while'");
  635. //Matched an 'l', move on to find an 'e'
  636. i = lnr.read();
  637. if(i == (int) 'e'){
  638. //System.err.println("Matched an 'e' in 'while'");
  639. i = lnr.read();
  640. /*
  641. * Most of the time this should be a '(', on the off
  642. * chance that it is not advance the input through
  643. * whitespace and comments.
  644. */
  645. boolean keepMoving = true;
  646. while(keepMoving){
  647. if(Character.isWhitespace((char)i)){
  648. i = lnr.read(); //Advance
  649. }
  650. else if(i == (int) '/'){
  651. //parsing comment
  652. i = matchComment(lnr);
  653. }
  654. else if(i == (int) '('){
  655. i = matchBrackets(lnr);
  656. }
  657. else{
  658. keepMoving = false;
  659. }
  660. }
  661. /*
  662. * Most of the time this should be a '{', on the off
  663. * chance that it is not advance the input through
  664. * whitespace and comments.
  665. */
  666. keepMoving = true;
  667. while(keepMoving){
  668. if(Character.isWhitespace((char)i)){
  669. i = lnr.read(); //Advance
  670. }
  671. else if(i == (int) '/'){
  672. //parsing comment
  673. i = matchComment(lnr);
  674. }
  675. else if(i == (int) '{'){
  676. //Correct usage of { ensured.
  677. //System.err.println("Complete & Correct!");
  678. return null;
  679. }
  680. else{
  681. keepMoving = false;
  682. }
  683. }
  684. //If we reach here then { was not used correctly so a warning is required
  685. if(clo.dFlag){
  686. err = new NccError(beginLine, 120);
  687. err.addTextln("Warning: Line " + beginLine + ": Poor block conversion after 'while'.");
  688. err.addTextln("\t" + sh.getLineNumber(beginLine));
  689. err.addTextln("\t" + sh.generateWhiteSpace(counter, beginLine) + "^");
  690. err.addTextln("DIAGNOSIS: The statement(s) in the 'while' section of the " +
  691. "while control statement beginning on line " + beginLine + " are not enclosed by " +
  692. "curly brackets, this may result in code ambiguity.");
  693. err.addText("See NCC Error Code 120 for more details");
  694. }
  695. break; //Matched entire 'while{' so break from while and return
  696. }
  697. }
  698. }
  699. }
  700. }
  701. }
  702. lnr.close();
  703. fr.close();
  704. }
  705. catch(IOException e){
  706. System.out.println("IOException: " + e.getMessage());
  707. e.printStackTrace();
  708. }
  709. return err;
  710. }
  711. /*
  712. * Note: There is not point matching normal brackets and reporting errors
  713. * about their usage in this class as they will have already be matched and
  714. * parsed correctly by the compiler(s) and thus any errors with them will
  715. * already have been reported.
  716. */
  717. /**
  718. * Matches brackets and returns when complete. This method is
  719. * recursive in nature, with each new opening bracket that is found a
  720. * new invocation of matchBrackets is started. When a closing bracket
  721. * is found a match has occurred and the method returns.
  722. *
  723. * This method essentially reads one character at a time simply looking for
  724. * a match.
  725. *
  726. * @param lnr The LineNumberReader we're working with.
  727. * @return The last integer lnr read.
  728. */
  729. private int matchBrackets(LineNumberReader lnr)
  730. {
  731. /*
  732. * When we're here we have read the first '('.
  733. */
  734. try {
  735. int i = lnr.read();
  736. while(i != -1){
  737. if(i == (int) '('){
  738. //New bracket block opened
  739. i = matchBrackets(lnr);
  740. }
  741. else if(i == (int) ')'){
  742. //Existing bracket block closed
  743. return lnr.read();
  744. }
  745. else{
  746. //Otherwise skip the contents of the brackets
  747. i = lnr.read();
  748. }
  749. }
  750. }
  751. catch(IOException e){
  752. System.out.println("IOException: " + e.getMessage());
  753. e.printStackTrace();
  754. }
  755. return (int) '@';
  756. }
  757. /*
  758. * In C multi-line comments are defined as "/* this is a comment */
  759. /**
  760. * Matches multi-line comments and returns true when complete.
  761. *
  762. * @param lnr The LineNumberReader we're working with.
  763. * @return The last integer lnr read.
  764. */
  765. private int matchComment(LineNumberReader lnr)
  766. {
  767. /*
  768. * When we're here we have read the first / so we're either looking at
  769. * a single line comment i.e. another / and skip until the end of the
  770. * line or we're looking for a * and skip until we find a * followed by
  771. * a /. If we find anything else then we return false.
  772. */
  773. try {
  774. int i;
  775. while((i = lnr.read()) != -1){
  776. if(i == (int) '/'){
  777. //Single line comment matching
  778. while((i = lnr.read()) != -1){
  779. if(i == (int) '\n'){
  780. return lnr.read();
  781. }
  782. }
  783. }
  784. else if(i == (int) '*'){
  785. //Multi-line comment
  786. while((i = lnr.read()) != -1){
  787. if(i == (int) '*'){
  788. i = lnr.read();
  789. if(i == (int) '/'){
  790. return lnr.read();
  791. }
  792. }
  793. }
  794. }
  795. else{
  796. return i;
  797. }
  798. }
  799. }
  800. catch(IOException e){
  801. System.out.println("IOException: " + e.getMessage());
  802. e.printStackTrace();
  803. }
  804. return 0;
  805. }
  806. /**
  807. * Converts a String to a Types value for processing decision making.
  808. *
  809. * @param str The String to return the value of.
  810. * @return The value of the String in the Types enum.
  811. */
  812. public static Types toType(String str)
  813. {
  814. try{
  815. return Types.valueOf(str);
  816. }
  817. catch(Exception ex){
  818. return Types.NOVALUE;
  819. }
  820. }
  821. /**
  822. * NCC Error Number(s): 121
  823. *
  824. * Analyses the line getchar() is made on to make sure it complies. If it
  825. * is not a correct call then an Error Message will be created and returned
  826. * by the method.
  827. *
  828. * @param j The NccPostProcessorJob to analyse. This object should in
  829. * fact be a NccPostProcessorAnalysisJob object as it will be
  830. * cast to this type of object first job in the method.
  831. * @return The NccError generated if there is one, null
  832. * otherwise.
  833. */
  834. private NccError checkGetchar(NccPostProcessorJob aj)
  835. {
  836. if(aj.getArgTokenList().size() != 0){
  837. NccError e = new NccError(aj.getBeginLine(), 121);
  838. e.addTextln("Error: Line " + e.getLine() + ": Function 'getchar' has been called with arguments but should not have been.");
  839. if(clo.dFlag){
  840. String calc = sh.getLineNumber(e.getLine());
  841. e.addTextln("\t" + calc);
  842. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("getchar("), e.getLine()) + "^");
  843. e.addTextln("DIAGNOSIS: To fix the error remove the argument in the call to 'getchar'");
  844. e.addText("See NCC Error Code 121 for more details.");
  845. }
  846. return e;
  847. }
  848. return null;
  849. }
  850. /**
  851. * NCC Error Number(s): 122
  852. *
  853. * Analyses the line putchar() is made on to make sure it complies. If it
  854. * is not a correct call then an Error Message will be created and returned
  855. * by the method.
  856. *
  857. * @param j The NccPostProcessorJob to analyse. This object should in
  858. * fact be a NccPostProcessorAnalysisJob object as it will be
  859. * cast to this type of object first job in the method.
  860. * @return The NccError generated if there is one, null
  861. * otherwise.
  862. */
  863. private NccError checkPutchar(NccPostProcessorJob aj)
  864. {
  865. if(aj.getArgTokenList().size() != 1){
  866. NccError e = new NccError(aj.getBeginLine(), 122);
  867. if(aj.getArgTokenList().size() == 0){
  868. e.addTextln("Error: Line " + e.getLine() + ": Function 'putchar' has been called with too few arguments.");
  869. }
  870. else{
  871. e.addTextln("Error: Line " + e.getLine() + ": Function 'putchar' has been called with too many arguments.");
  872. }
  873. if(clo.dFlag){
  874. String calc = sh.getLineNumber(e.getLine());
  875. e.addTextln("\t" + calc);
  876. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("putchar("), e.getLine()) + "^");
  877. e.addTextln("DIAGNOSIS: To fix the error ensure only one char (or int) argument is passed to 'putchar'");
  878. e.addText("See NCC Error Code 122 for more details.");
  879. }
  880. return e;
  881. }
  882. else{
  883. //Number of args to putchar is 1, check it is a char or and int
  884. if( (aj.getArgTokenList().get(0).equals("char")) || (aj.getArgTokenList().get(0).equals("int")) ){
  885. //No error
  886. return null;
  887. }
  888. else{
  889. NccError e = new NccError(aj.getBeginLine(), 122);
  890. e.addTextln("Error: Line " + e.getLine() + ": The argument passed to 'putchar' was not a valid char or int. 'putchar' was in fact passed a " + aj.getArgTokenList().get(0) + ".");
  891. if(clo.dFlag){
  892. String calc = sh.getLineNumber(e.getLine());
  893. e.addTextln("\t" + calc);
  894. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("putchar("), e.getLine()) + "^");
  895. e.addTextln("DIAGNOSIS: To fix the error ensure the value or variable argument passed to 'putchar' is a char or an int.");
  896. e.addText("See NCC Error Code 122 for more details.");
  897. }
  898. return e;
  899. }
  900. }
  901. }
  902. /*
  903. * Notes: The valid string format characters for printf:
  904. * Character Argument Type: Printed as
  905. * d,i int; decimal number
  906. * o int; octal number
  907. * x,X int; hexadecimal number
  908. * u int; unsigned decimal number
  909. * c int; single char
  910. * s char *; prints a string "", terminated by '\0'
  911. * f double; [-]m.dddddd
  912. * e,E double; [-]m.dddddde+-xx or [-]m.ddddddE+-xx
  913. * g,G double; prints %f or %[e,E] as appropriate
  914. * p void *; pointer
  915. * % print a & character
  916. *
  917. * Other formatting considerations include spatial specifications. e.g.
  918. *
  919. * :%s: :hello, world:
  920. * :%10s: :hello, world:
  921. * :%.10s: :hello, wor:
  922. * :%-10s: :hello, world:
  923. * :%.15s: :hello, world:
  924. * :%-15s: :hello, world :
  925. * :%15.10s: : hello, wor:
  926. * :%-15.10s: :hello, wor :
  927. *
  928. * Therefore between the % and the valid letters from the table above
  929. * e.g. 'd', the valid characters are: 0-9
  930. * .*, .#, -, +, ' '(space), ', I
  931. * hh, h, l, ll, j, z, L,
  932. *
  933. *
  934. * Table taken from:
  935. * Kernighan B. W. & Ritchie D. M, The C Programming Language, Second
  936. * Edition. Prentice Hall: New Jersey. p. 154.
  937. */
  938. /**
  939. * NCC Error Number(s): 123
  940. *
  941. * Analyses the line printf(...) is made on to make sure it complies. If it
  942. * is not a correct call then an Error Message will be created and returned
  943. * by the method.
  944. *
  945. * Note: "char aorp" is equiv. to "string" for type of arg
  946. *
  947. * @param j The NccPostProcessorJob to analyse. This object should in
  948. * fact be a NccPostProcessorAnalysisJob object as it will be
  949. * cast to this type of object first job in the method.
  950. * @return The NccError generated if there is one, null
  951. * otherwise.
  952. */
  953. private NccError checkPrintf(NccPostProcessorJob aj)
  954. {
  955. NccError e = new NccError();
  956. ArrayList<String> formatOrder = new ArrayList<String>();
  957. /*
  958. * See tables above for valid formatting characters in printf.
  959. */
  960. //Get the format string
  961. String format = sh.getLineNumber(aj.getBeginLine());
  962. format = format.substring(format.indexOf('"', 0)+1, format.indexOf('"', format.indexOf('"', 0)+1));
  963. char[] cArray = format.toCharArray();
  964. int i = 0;
  965. //Consume characters until a '%' is found
  966. while(i < cArray.length){
  967. if(cArray[i] == '%'){
  968. i++;
  969. while(!validPrintfEnds.contains(Character.toString(cArray[i]))){
  970. if(validPrintfMids.contains(Character.toString(cArray[i]))){
  971. i++;
  972. }
  973. else{
  974. //The character was not recognised as a valid printf formatter (conversion character)
  975. e.setLine(aj.getBeginLine());
  976. e.setErrorNumber(123);
  977. e.addTextln("Warning: Line: " + e.getLine() + ": '" + cArray[i] + "' is not a valid printf string conversion character.");
  978. if(clo.dFlag){
  979. String calc = sh.getLineNumber(e.getLine());
  980. e.addTextln("\t" + calc);
  981. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("printf(")+9+i, e.getLine()) + "^");
  982. }
  983. i++;
  984. break; //Valid conversion char not found move on to next '%'
  985. }
  986. }
  987. if(validPrintfEnds.contains(Character.toString(cArray[i]))){
  988. //If the character is a valid end char find out what it is
  989. switch((int) cArray[i]){
  990. case ((int)'d') : formatOrder.add("int"); break;
  991. case ((int)'i') : formatOrder.add("int"); break;
  992. case ((int)'o') : formatOrder.add("octal"); break;
  993. case ((int)'x') : formatOrder.add("hex"); break;
  994. case ((int)'X') : formatOrder.add("hex"); break;
  995. case ((int)'u') : formatOrder.add("int"); break;
  996. case ((int)'c') : formatOrder.add("char"); break;
  997. case ((int)'s') : formatOrder.add("string"); break;
  998. case ((int)'f') : formatOrder.add("float"); break;
  999. case ((int)'e') : formatOrder.add("float"); break;
  1000. case ((int)'E') : formatOrder.add("float"); break;
  1001. case ((int)'g') : formatOrder.add("float"); break;
  1002. case ((int)'G') : formatOrder.add("float"); break;
  1003. case ((int)'p') : formatOrder.add("pointer"); break;
  1004. case ((int)'%') : formatOrder.add("%"); break;
  1005. default : break;
  1006. }
  1007. i++;
  1008. }
  1009. }
  1010. else{
  1011. //Consume
  1012. i++;
  1013. }
  1014. }
  1015. /*
  1016. * Compare the lists: conversion char vs. arguments, remember that the
  1017. * size of the aj.getArgTokenList() ArrayList should be be one greater
  1018. * than the number of conversion chars because the initial String
  1019. * containing the formatting is also included in that count.
  1020. */
  1021. if(formatOrder.size() == aj.getArgTokenList().size()-1){
  1022. /*
  1023. * The lists are the same size, check the types etc.
  1024. *
  1025. * Begin by discarding the fist element of the list of args and
  1026. * exchanging any args of type "char aorp" to type "string".
  1027. */
  1028. ArrayList<String> argsList = new ArrayList<String>();
  1029. for(int j = 1; j < aj.getArgTokenList().size(); j++){
  1030. String t;
  1031. if( ((t = aj.getArgTokenList().get(j)).equals("char aorp")) || (t.equals("int aorp")) ){
  1032. argsList.add("string");
  1033. }
  1034. else{
  1035. argsList.add(aj.getArgTokenList().get(j));
  1036. }
  1037. }
  1038. for(int j = 0; j < argsList.size(); j++){
  1039. if(argsList.get(j).equals(formatOrder.get(j))){
  1040. //No Error
  1041. }
  1042. else{
  1043. //Error
  1044. e.setLine(aj.getBeginLine());
  1045. e.setErrorNumber(123);
  1046. e.addTextln("Warning: Line: " + e.getLine() + ": 'printf' conversion character/argument type mismatch.");
  1047. if(clo.dFlag){
  1048. String stndrdth = "th";
  1049. switch((j+2)%10){
  1050. case 0 : stndrdth = "th"; break;
  1051. case 1 : stndrdth = "st"; break;
  1052. case 2 : stndrdth = "nd"; break;
  1053. case 3 : stndrdth = "rd"; break;
  1054. case 4 : stndrdth = "th"; break;
  1055. case 5 : stndrdth = "th"; break;
  1056. case 6 : stndrdth = "th"; break;
  1057. case 7 : stndrdth = "th"; break;
  1058. case 8 : stndrdth = "th"; break;
  1059. case 9 : stndrdth = "th"; break;
  1060. }
  1061. String calc = sh.getLineNumber(e.getLine());
  1062. e.addTextln("\t" + calc);
  1063. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("printf("), e.getLine()) + "^");
  1064. e.addTextln("DIAGNOSIS: The " + (j+2) + stndrdth + " conversion character/argument pair are not the same type.");
  1065. e.addTextln("Format string expected '" + formatOrder.get(j) + "' but '" + argsList.get(j) + "' was found in the arguments!");
  1066. }
  1067. }
  1068. }
  1069. }
  1070. else{
  1071. //The lists are not the same size
  1072. if(formatOrder.size() < aj.getArgTokenList().size()-1){
  1073. //More arguments than conversion characters.
  1074. e.setLine(aj.getBeginLine());
  1075. e.setErrorNumber(123);
  1076. e.addTextln("Warning: Line: " + e.getLine() + ": 'printf' called with too many arguments.");
  1077. if(clo.dFlag){
  1078. String calc = sh.getLineNumber(e.getLine());
  1079. e.addTextln("\t" + calc);
  1080. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("printf("), e.getLine()) + "^");
  1081. e.addTextln("DIAGNOSIS: The formatted string in printf contains " + formatOrder.size() + " conversion characters " +
  1082. "however it was passed " + (aj.getArgTokenList().size()-1) + " valid arguments.");
  1083. e.addTextln("To fix the error include an extra conversion character(s) in the format string or remove the appropriate argument(s).");
  1084. }
  1085. }
  1086. else{
  1087. //More conversion characters than arguments.
  1088. e.setLine(aj.getBeginLine());
  1089. e.setErrorNumber(123);
  1090. e.addTextln("Warning: Line: " + e.getLine() + ": The 'printf' format string includes too many conversion characters for the number of arguments passed.");
  1091. if(clo.dFlag){
  1092. String calc = sh.getLineNumber(e.getLine());
  1093. e.addTextln("\t" + calc);
  1094. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("printf("), e.getLine()) + "^");
  1095. e.addTextln("DIAGNOSIS: The formatted string in printf contains " + formatOrder.size() + " conversion characters " +
  1096. "however it was only passed " + (aj.getArgTokenList().size()-1) + " valid arguments.");
  1097. e.addTextln("To fix the error remove the extra conversion character(s) in the format string or include another argument(s).");
  1098. }
  1099. }
  1100. }
  1101. if(clo.dFlag){
  1102. //Set the Error number for the error (if one was created).
  1103. e.addText("See NCC Error Code 123 for more details.");
  1104. }
  1105. //Return the error if there was one
  1106. if(e.getErrorNumber() == 0){
  1107. return null;
  1108. }
  1109. else{
  1110. return e;
  1111. }
  1112. }
  1113. /*
  1114. * Notes: The valid string format characters for scanf:
  1115. * Character Argument Type: Printed as
  1116. * d int *; decimal integer
  1117. * i int *; integer, hexadecimal, octal
  1118. * o int *; octal integer
  1119. * u unsigned int*; unsigned decimal integer
  1120. * x int *; hexadecimal integer
  1121. * c char *; characters
  1122. * s char *; character string
  1123. * e,f,g float *; floating point number
  1124. * % literal %; no assignment is made
  1125. *
  1126. * Table taken from:
  1127. * Kernighan B. W. & Ritchie D. M, The C Programming Language, Second
  1128. * Edition. Prentice Hall: New Jersey. p. 158.
  1129. */
  1130. /**
  1131. * NCC Error Number(s): 124 (Set as 123 for GCC parsing reasons)
  1132. *
  1133. * Analyses the line scanf(...) is made on to make sure it complies. If it
  1134. * is not a correct call then an Error Message will be created and returned
  1135. * by the method.
  1136. *
  1137. * @param j The NccPostProcessorJob to analyse. This object should in
  1138. * fact be a NccPostProcessorAnalysisJob object as it will be
  1139. * cast to this type of object first job in the method.
  1140. * @return The NccError generated if there is one, null
  1141. * otherwise.
  1142. */
  1143. private NccError checkScanf(NccPostProcessorJob aj)
  1144. {
  1145. NccError e = new NccError();
  1146. ArrayList<String> formatOrder = new ArrayList<String>();
  1147. /*
  1148. * See tables above for valid formatting characters in scanf.
  1149. */
  1150. //Get the format string
  1151. String format = sh.getLineNumber(aj.getBeginLine());
  1152. format = format.substring(format.indexOf('"', 0)+1, format.indexOf('"', format.indexOf('"', 0)+1));
  1153. char[] cArray = format.toCharArray();
  1154. int i = 0;
  1155. //Consume characters until a '%' is found
  1156. while(i < cArray.length){
  1157. if(cArray[i] == '%'){
  1158. i++;
  1159. while(!validScanfEnds.contains(Character.toString(cArray[i]))){
  1160. if(validScanfMids.contains(Character.toString(cArray[i]))){
  1161. i++;
  1162. }
  1163. else{
  1164. //The character was not recognised as a valid scanf conversion character
  1165. e.setLine(aj.getBeginLine());
  1166. e.setErrorNumber(123);
  1167. e.addTextln("Warning: Line: " + e.getLine() + ": '" + cArray[i] + "' is not a valid scanf string conversion character.");
  1168. if(clo.dFlag){
  1169. String calc = sh.getLineNumber(e.getLine());
  1170. e.addTextln("\t" + calc);
  1171. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("scanf(")+9+i, e.getLine()) + "^");
  1172. }
  1173. i++;
  1174. break; //Valid conversion char not found move on to next '%'
  1175. }
  1176. }
  1177. if(validScanfEnds.contains(Character.toString(cArray[i]))){
  1178. //If the character is a valid end char find out what it is
  1179. switch((int) cArray[i]){
  1180. case ((int)'d') : formatOrder.add("int"); break;
  1181. case ((int)'i') : formatOrder.add("int"); break;
  1182. case ((int)'o') : formatOrder.add("octal"); break;
  1183. case ((int)'u') : formatOrder.add("int"); break;
  1184. case ((int)'x') : formatOrder.add("hex"); break;
  1185. case ((int)'c') : formatOrder.add("char"); break;
  1186. case ((int)'s') : formatOrder.add("string"); break;
  1187. case ((int)'e') : formatOrder.add("float"); break;
  1188. case ((int)'f') : formatOrder.add("float"); break;
  1189. case ((int)'g') : formatOrder.add("float"); break;
  1190. case ((int)'%') : formatOrder.add("%"); break;
  1191. default : break;
  1192. }
  1193. i++;
  1194. }
  1195. }
  1196. else{
  1197. //Consume
  1198. i++;
  1199. }
  1200. }
  1201. /*
  1202. * Compare the lists: conversion char vs. arguments, remember that the
  1203. * size of the aj.getArgTokenList() ArrayList should be be one greater
  1204. * than the number of conversion chars because the initial String
  1205. * containing the formatting is also included in that count.
  1206. */
  1207. if(formatOrder.size() == aj.getArgTokenList().size()-1){
  1208. /*
  1209. * The lists are the same size, check the types etc.
  1210. *
  1211. * Begin by discarding the fist element of the list of args and
  1212. * exchanging any args of type "char aorp" to type "string".
  1213. */
  1214. ArrayList<String> argsList = new ArrayList<String>();
  1215. for(int j = 1; j < aj.getArgTokenList().size(); j++){
  1216. /*
  1217. * The second conversion that takes place in the printf method
  1218. * above has been removed from the line below. There is a
  1219. * possibility this will casue typing errors...not sure?
  1220. */
  1221. if( (aj.getArgTokenList().get(j).equals("char aorp"))){
  1222. argsList.add("string");
  1223. }
  1224. else{
  1225. argsList.add(aj.getArgTokenList().get(j));
  1226. }
  1227. }
  1228. for(int j = 0; j < argsList.size(); j++){
  1229. if(argsList.get(j).equals(formatOrder.get(j))){
  1230. //No type errors
  1231. }
  1232. else{
  1233. //Error
  1234. e.setLine(aj.getBeginLine());
  1235. e.setErrorNumber(123);
  1236. e.addTextln("Warning: Line: " + e.getLine() + ": 'scanf' conversion character/argument type mismatch.");
  1237. if(clo.dFlag){
  1238. String stndrdth = "th";
  1239. switch((j+2)%10){
  1240. case 0 : stndrdth = "th"; break;
  1241. case 1 : stndrdth = "st"; break;
  1242. case 2 : stndrdth = "nd"; break;
  1243. case 3 : stndrdth = "rd"; break;
  1244. case 4 : stndrdth = "th"; break;
  1245. case 5 : stndrdth = "th"; break;
  1246. case 6 : stndrdth = "th"; break;
  1247. case 7 : stndrdth = "th"; break;
  1248. case 8 : stndrdth = "th"; break;
  1249. case 9 : stndrdth = "th"; break;
  1250. }
  1251. String calc = sh.getLineNumber(e.getLine());
  1252. e.addTextln("\t" + calc);
  1253. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("printf("), e.getLine()) + "^");
  1254. e.addTextln("DIAGNOSIS: The " + (j+2) + stndrdth + " conversion character/argument pair are not the same type.");
  1255. e.addTextln("Format string expected '" + formatOrder.get(j) + "' but '" + argsList.get(j) + "' was found in the arguments!");
  1256. }
  1257. }
  1258. }
  1259. /*
  1260. * Check that the arguments passed are all addresses in
  1261. * momory (pointers).
  1262. *
  1263. * Begin by breaking up the call in to blocks ot arguments
  1264. * and storing the args in an ordered ArrayList.
  1265. */
  1266. String working = sh.getLineNumber(aj.getBeginLine());
  1267. StringTokenizer st = new StringTokenizer(working, ",");
  1268. //Discard the first argument (formatted string)
  1269. if(st.hasMoreTokens()){
  1270. st.nextToken();
  1271. }
  1272. //Store the rest of the tokens in an ArrayList
  1273. ArrayList<String> checker = new ArrayList<String>();
  1274. while(st.hasMoreTokens()){
  1275. checker.add(st.nextToken().trim());
  1276. }
  1277. /*
  1278. * Now check the types of the arguments against the string
  1279. * representing it to ensure it is an address in memory. If
  1280. * the type is "string" then this is already a pointer or
  1281. * array so there is no need to check these.
  1282. */
  1283. for(int y = 0; y < argsList.size(); y++){
  1284. if(argsList.get(y).equals("string")){
  1285. //Check the argument string to ensure it doesn't start with &
  1286. if(checker.get(y).startsWith("&")){
  1287. //Warning: Variable begins with & so is an address to a pointer which is probably non-sence!
  1288. e.setLine(aj.getBeginLine());
  1289. e.setErrorNumber(123);
  1290. String stndrdth = "th";
  1291. switch((y+2)%10){
  1292. case 0 : stndrdth = "th"; break;
  1293. case 1 : stndrdth = "st"; break;
  1294. case 2 : stndrdth = "nd"; break;
  1295. case 3 : stndrdth = "rd"; break;
  1296. case 4 : stndrdth = "th"; break;
  1297. case 5 : stndrdth = "th"; break;
  1298. case 6 : stndrdth = "th"; break;
  1299. case 7 : stndrdth = "th"; break;
  1300. case 8 : stndrdth = "th"; break;
  1301. case 9 : stndrdth = "th"; break;
  1302. }
  1303. e.addTextln("Warning: Line: " + e.getLine() + ": The " + (y+2) + stndrdth + " argument to 'scanf' is already an address in memory (pointer).");
  1304. if(clo.dFlag){
  1305. String calc = sh.getLineNumber(e.getLine());
  1306. e.addTextln("\t" + calc);
  1307. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf(checker.get(y))+1, e.getLine()) + "^");
  1308. e.addTextln("DIAGNOSIS: Argument '" + checker.get(y) + "' is already an address in memory (pointer/array), therefore '&' probably doesn't need to be used in order to assign a value to it.");
  1309. e.addTextln("The warning can therefore be removed by deleting the & character.");
  1310. }
  1311. }
  1312. }
  1313. else{
  1314. if(checker.get(y).startsWith("&")){
  1315. //Variable begins with &... so is address
  1316. }
  1317. else{
  1318. //Error...
  1319. e.setLine(aj.getBeginLine());
  1320. e.setErrorNumber(123);
  1321. String stndrdth = "th";
  1322. switch((y+2)%10){
  1323. case 0 : stndrdth = "th"; break;
  1324. case 1 : stndrdth = "st"; break;
  1325. case 2 : stndrdth = "nd"; break;
  1326. case 3 : stndrdth = "rd"; break;
  1327. case 4 : stndrdth = "th"; break;
  1328. case 5 : stndrdth = "th"; break;
  1329. case 6 : stndrdth = "th"; break;
  1330. case 7 : stndrdth = "th"; break;
  1331. case 8 : stndrdth = "th"; break;
  1332. case 9 : stndrdth = "th"; break;
  1333. }
  1334. e.addTextln("Error: Line: " + e.getLine() + ": The " + (y+2) + stndrdth + " argument to 'scanf' is not an address in memory (pointer).");
  1335. if(clo.dFlag){
  1336. String calc = sh.getLineNumber(e.getLine());
  1337. e.addTextln("\t" + calc);
  1338. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf(checker.get(y))+1, e.getLine()) + "^");
  1339. e.addTextln("DIAGNOSIS: Argument '" + checker.get(y) + "' is not an address in memory.");
  1340. e.addTextln("If '" + checker.get(y) + "' is a variable insert a '&' character in order to point to its' address in memory.");
  1341. }
  1342. }
  1343. }
  1344. }
  1345. }
  1346. else{
  1347. //The lists are not the same size
  1348. if(formatOrder.size() < aj.getArgTokenList().size()-1){
  1349. //More arguments than conversion characters.
  1350. e.setLine(aj.getBeginLine());
  1351. e.setErrorNumber(123);
  1352. e.addTextln("Warning: Line: " + e.getLine() + ": 'scanf' called with too many arguments.");
  1353. if(clo.dFlag){
  1354. String calc = sh.getLineNumber(e.getLine());
  1355. e.addTextln("\t" + calc);
  1356. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("scanf("), e.getLine()) + "^");
  1357. e.addTextln("DIAGNOSIS: The formatted string in scanf contains " + formatOrder.size() + " conversion characters " +
  1358. "however it was passed " + (aj.getArgTokenList().size()-1) + " valid arguments.");
  1359. e.addTextln("To fix the error include an extra conversion character(s) in the format string or remove the appropriate argument(s).");
  1360. }
  1361. }
  1362. else{
  1363. //More conversion characters than arguments.
  1364. e.setLine(aj.getBeginLine());
  1365. e.setErrorNumber(123);
  1366. e.addTextln("Warning: Line: " + e.getLine() + ": The 'scanf' format string includes too many conversion characters for the number of arguments passed.");
  1367. if(clo.dFlag){
  1368. String calc = sh.getLineNumber(e.getLine());
  1369. e.addTextln("\t" + calc);
  1370. e.addTextln("\t" + sh.generateWhiteSpace(calc.indexOf("scanf("), e.getLine()) + "^");
  1371. e.addTextln("DIAGNOSIS: The formatted string in scanf contains " + formatOrder.size() + " conversion characters " +
  1372. "however it was only passed " + (aj.getArgTokenList().size()-1) + " valid arguments.");
  1373. e.addTextln("To fix the error remove the extra conversion character(s) in the format string or include another argument(s).");
  1374. }
  1375. }
  1376. }
  1377. if(clo.dFlag){
  1378. //Set the Error number for the error (if one was created).
  1379. e.addText("See NCC Error Code 124 for more details.");
  1380. }
  1381. //Return the error if there was one
  1382. if(e.getErrorNumber() == 0){
  1383. return null;
  1384. }
  1385. else{
  1386. return e;
  1387. }
  1388. }
  1389. /**
  1390. * Initialises the list of Valid Printf Ends.
  1391. */
  1392. private void initValidPrintfEnds()
  1393. {
  1394. validPrintfEnds.add("d");
  1395. validPrintfEnds.add("i");
  1396. validPrintfEnds.add("o");
  1397. validPrintfEnds.add("x");
  1398. validPrintfEnds.add("X");
  1399. validPrintfEnds.add("u");
  1400. validPrintfEnds.add("c");
  1401. validPrintfEnds.add("s");
  1402. validPrintfEnds.add("f");
  1403. validPrintfEnds.add("e");
  1404. validPrintfEnds.add("E");
  1405. validPrintfEnds.add("g");
  1406. validPrintfEnds.add("G");
  1407. validPrintfEnds.add("p");
  1408. validPrintfEnds.add("%");
  1409. }
  1410. /**
  1411. * Initialises the list of Valid Printf Mids.
  1412. */
  1413. private void initValidPrintfMids()
  1414. {
  1415. validPrintfMids.add("0");
  1416. validPrintfMids.add("1");
  1417. validPrintfMids.add("2");
  1418. validPrintfMids.add("3");
  1419. validPrintfMids.add("4");
  1420. validPrintfMids.add("5");
  1421. validPrintfMids.add("6");
  1422. validPrintfMids.add("7");
  1423. validPrintfMids.add("8");
  1424. validPrintfMids.add("9");
  1425. validPrintfMids.add(".");
  1426. validPrintfMids.add("-");
  1427. validPrintfMids.add("+");
  1428. validPrintfMids.add("*");
  1429. validPrintfMids.add("#");
  1430. validPrintfMids.add(" ");
  1431. validPrintfMids.add("'");
  1432. validPrintfMids.add("I");
  1433. validPrintfMids.add("h");
  1434. validPrintfMids.add("l");
  1435. validPrintfMids.add("j");
  1436. validPrintfMids.add("z");
  1437. validPrintfMids.add("L");
  1438. }
  1439. /**
  1440. * Initialises the list of Valid Scanf Ends.
  1441. */
  1442. private void initValidScanfEnds()
  1443. {
  1444. validScanfEnds.add("d");
  1445. validScanfEnds.add("i");
  1446. validScanfEnds.add("o");
  1447. validScanfEnds.add("u");
  1448. validScanfEnds.add("x"

Large files files are truncated, but you can click here to view the full file