ChipMaster's bwBASIC This also includes history going back to v2.10. *WARN* some binary files might have been corrupted by CRLF.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

619 lines
16 KiB

  1. /*-------------------------------------------------------------------*/
  2. /* renum.c -- Renumbers a BASIC program in an ASCII file. */
  3. /* Originally written in HP 2000 BASIC by David Lance Robinson, 1977 */
  4. /* Adapted to MS BASIC and translated to C 4/1995 by Jon B. Volkoff */
  5. /* (eidetics@cerf.net) */
  6. /* */
  7. /* Some changes 04-2020 Ken. Re cp or copy and input terminator */
  8. /* when compiling under DOS use -DMSDOS */
  9. /* And fgets under Ubuntu. */
  10. /*-------------------------------------------------------------------*/
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #define MAX_LINE_LENGTH 255
  15. #define MAX_LINE_COUNT 1500
  16. int instr();
  17. char *midstr1();
  18. char *midstr2();
  19. char *myfget;
  20. void binary_search(void);
  21. int f2, l2, n, x;
  22. int sidx[MAX_LINE_COUNT][2];
  23. int myretn;
  24. char rstr[MAX_LINE_LENGTH];
  25. int main(argc, argv)
  26. int argc;
  27. char *argv[];
  28. {
  29. int f, d, s, p, s1, t, l, g;
  30. int c, f1, c1, i, f8, r, l1, l3;
  31. int v1, f6, l6, b, f9, x9, b1, p8, p9, a, d9;
  32. char pstr[MAX_LINE_LENGTH];
  33. char sstr[MAX_LINE_LENGTH];
  34. char f9str[MAX_LINE_LENGTH];
  35. char s9str[MAX_LINE_LENGTH];
  36. char tempstr[MAX_LINE_LENGTH + 64];
  37. FILE *fdin;
  38. FILE *fdout;
  39. int skip, bp, temp, getout, disp_msg;
  40. f = 1;
  41. printf("Version 04/30/2020\n");
  42. if (argc > 1) strcpy(pstr, argv[1]);
  43. else
  44. {
  45. printf("Program in file? ");
  46. myfget=fgets(pstr,MAX_LINE_LENGTH, stdin);
  47. if (strchr(pstr, '\n') != NULL)
  48. {
  49. pstr[strlen(pstr)-1] = '\0'; /* NULL terminate input. Ken */
  50. }
  51. }
  52. if (strlen(pstr) == 0) strcpy(pstr, "0.doc");
  53. fdin = fopen(pstr, "r");
  54. if (fdin == NULL)
  55. {
  56. printf("Unable to open input file\n");
  57. exit(1);
  58. }
  59. strcpy(f9str, pstr);
  60. #if defined(__MVS__) || defined(__CMS__)
  61. strcpy(pstr, "dd:editfl");
  62. #else
  63. strcpy(pstr, "editfl");
  64. #endif
  65. fdout = fopen(pstr, "w");
  66. /* After editfl is created it is left behind. Ken */
  67. if (fdout == NULL)
  68. {
  69. printf("Unable to open temporary file editfl for output\n");
  70. exit(1);
  71. }
  72. /* Main program begins here */
  73. s = 0; l2 = 0; d = 0;
  74. f2 = 10000;
  75. printf ("PLEASE WAIT A FEW SECONDS!\n");
  76. while (fgets(pstr, MAX_LINE_LENGTH, fdin) != NULL)
  77. {
  78. pstr[strlen(pstr) - 1] = '\0';
  79. p = instr(pstr, " ");
  80. if (p != 0 && p <= 5)
  81. {
  82. n = atoi(midstr2(pstr, 1, p));
  83. if (n != 0)
  84. {
  85. s++;
  86. if( s < MAX_LINE_COUNT )
  87. {
  88. /* OK */
  89. }
  90. else
  91. {
  92. printf("Too many lines. Over %d\n",MAX_LINE_COUNT);
  93. exit(1);
  94. }
  95. sidx[s][0] = n;
  96. s1 = s;
  97. while (s1 >= 2)
  98. {
  99. s1--;
  100. if (sidx[s1][0] < sidx[s1 + 1][0]) break;
  101. if (sidx[s1][0] == sidx[s1 + 1][0])
  102. {
  103. printf("ERROR !!! MORE THAN ONE STATEMENT FOR A ");
  104. printf("STATEMENT NUMBER\n");
  105. exit(1);
  106. }
  107. t = sidx[s1][0];
  108. sidx[s1][0] = sidx[s1 + 1][0];
  109. sidx[s1 + 1][0] = t;
  110. }
  111. }
  112. }
  113. }
  114. fclose(fdin);
  115. if (s == 0)
  116. {
  117. printf("Programs must start with a number in column 1\n");
  118. printf("NO PROGRAM IS IN THE FILE!\n");
  119. exit(1);
  120. }
  121. strcpy(pstr, "");
  122. for (l = 1; l <= s; l++)
  123. sidx[l][1] = sidx[l][0];
  124. g = 1;
  125. disp_msg = 1;
  126. /*------------------------------------------------------------------------*/
  127. /* Find out how and what to renumber (using HP BASIC renumber parameters) */
  128. /* MS BASIC renumber is: RENUM (newnum) (,(oldnum) (,increment)) */
  129. /*------------------------------------------------------------------------*/
  130. while(1)
  131. {
  132. if (disp_msg == 1)
  133. {
  134. printf("RENUMBER (-starting number (,interval (,first statement ");
  135. printf("(,last))))\n");
  136. disp_msg = 0;
  137. }
  138. skip = 0;
  139. bp = 0;
  140. printf("RENUMBER-");
  141. myfget=fgets(pstr,MAX_LINE_LENGTH,stdin);
  142. p = strlen(pstr);
  143. if (g == 0)
  144. {
  145. if (strlen(pstr) == 0) break;
  146. if (p == 0) skip = 1;
  147. else
  148. {
  149. t = atoi(midstr2(pstr, 1, 1));
  150. if (t == 0) break;
  151. }
  152. }
  153. if (strlen(pstr) == 0) skip = 1;
  154. if (skip == 0)
  155. {
  156. c = instr(pstr, ",");
  157. temp = 0; if (c != 0) temp = -1;
  158. f1 = atoi(midstr2(pstr, 1, p + temp*(p - c + 1)));
  159. if (f1 == 0) bp = 1;
  160. if (c == 0) skip = 2;
  161. }
  162. if (skip == 0 && bp == 0)
  163. {
  164. c1 = instr(midstr1(pstr, c + 1), ",") + c;
  165. temp = 0; if (c1 != c) temp = -1;
  166. i = atoi(midstr2(pstr, c + 1, p + temp*(p - c1 + 1) - c));
  167. if (i == 0) bp = 1;
  168. if (c1 == c) skip = 3;
  169. }
  170. if (skip == 0 && bp == 0)
  171. {
  172. c = instr(midstr1(pstr, c1 + 1), ",") + c1;
  173. temp = 0; if (c != c1) temp = -1;
  174. f8 = atoi(midstr2(pstr, c1 + 1, p + temp*(p - c + 1) - c1));
  175. if (f8 == 0) bp = 1;
  176. if (c == c1) skip = 4;
  177. }
  178. if (skip == 0 && bp == 0)
  179. {
  180. l = atoi(midstr1(pstr, c + 1));
  181. if (l == 0) bp = 1;
  182. }
  183. if (bp == 0) switch (skip)
  184. {
  185. case 1:
  186. f1 = 10;
  187. i = 10;
  188. f8 = 1;
  189. l = 99999;
  190. break;
  191. case 2:
  192. i = 10;
  193. f8 = 1;
  194. l = 99999;
  195. break;
  196. case 3:
  197. f8 = 1;
  198. l = 99999;
  199. break;
  200. case 4:
  201. l = 99999;
  202. break;
  203. }
  204. if (f1 < 1 || i == 0 || f8 < 1 || l < 1) bp = 1;
  205. if (f1 > 99999 || i > 99999 || f8 > 99999 || l > 99999 || f8 > l)
  206. bp = 1;
  207. c = 0;
  208. for (r = 1; r <= s; r++)
  209. if (sidx[r][0] >= f8 && sidx[r][0] <= l) c = c + 1;
  210. if (c == 0)
  211. {
  212. printf("There is nothing to renumber !!\n");
  213. disp_msg = 1;
  214. }
  215. /*------------------------------------*/
  216. /* Make list of new statement numbers */
  217. /*------------------------------------*/
  218. l1 = f1 + (c - 1)*i;
  219. if (l1 < 1 || l1 > 99999) bp = 1;
  220. x = 0; c = 0;
  221. if (bp == 0 && disp_msg == 0) for (r = 1; r <= s; r++)
  222. {
  223. if (sidx[r][0] < f8 || sidx[r][0] > l)
  224. if (sidx[r][1] >= f1 && sidx[r][1] <= l1)
  225. {
  226. printf("SEQUENCE NUMBER OVERLAP\n");
  227. exit(1);
  228. }
  229. else {}
  230. else
  231. {
  232. if (sidx[r][0] != f1 + c*i)
  233. {
  234. if (x == 0)
  235. {
  236. if (r < f2) f2 = r;
  237. x = 1;
  238. }
  239. if (r > l2) l2 = r;
  240. }
  241. sidx[r][1] = f1 + c*i;
  242. c++;
  243. l3 = r;
  244. }
  245. }
  246. if (bp == 0 && disp_msg == 0) g = 0;
  247. if (bp == 1) printf("BAD PARAMETER\n");
  248. }
  249. /*-------------------*/
  250. /* Start renumbering */
  251. /*-------------------*/
  252. if (l2 == 0)
  253. {
  254. printf("NOTHING RENUMBERED!\n");
  255. exit(1);
  256. }
  257. printf("RENUMBERING\n");
  258. /*
  259. for (r = 1; r <= s; r ++)
  260. printf("%d -> %d\n", sidx[r][0], sidx[r][1]);
  261. */
  262. printf("VERIFY? N or n cancels:");
  263. myfget=fgets(pstr,MAX_LINE_LENGTH,stdin);
  264. v1 = 0;
  265. if (strcmp(midstr2(pstr, 1, 1), "N") == 0) v1 = 1; /* Except n or N. Ken */
  266. if (strcmp(midstr2(pstr, 1, 1), "n") == 0) v1 = 1;
  267. if (v1 == 1) {
  268. printf("Operation cancelled\n");
  269. exit(1);
  270. }
  271. fdin = fopen(f9str, "r");
  272. if (fdin == NULL)
  273. {
  274. printf("Unable to open input file\n");
  275. exit(1);
  276. }
  277. f6 = sidx[f2][0];
  278. l6 = sidx[l2][0];
  279. while (fgets(pstr, MAX_LINE_LENGTH, fdin) != NULL)
  280. {
  281. pstr[strlen(pstr) - 1] = '\0';
  282. b = instr(pstr, " ");
  283. if (b != 0)
  284. {
  285. n = atoi(midstr2(pstr, 1, b));
  286. if (n != 0)
  287. {
  288. if (n >= f6 && n <= l6)
  289. {
  290. binary_search();
  291. if (x == 0)
  292. {
  293. strcat(rstr, midstr1(pstr, b));
  294. strcpy(pstr, rstr);
  295. b = instr(pstr, " ");
  296. }
  297. }
  298. b++;
  299. /*-------------------------------------------------------------*/
  300. /* There are differences, of course, between processing for HP */
  301. /* BASIC and MS BASIC. */
  302. /* */
  303. /* CONVERT, PRINT USING, and MAT PRINT USING changes are not */
  304. /* applicable in MS BASIC. */
  305. /* */
  306. /* Had to also add capability for multiple statements here. */
  307. /*-------------------------------------------------------------*/
  308. while(1)
  309. {
  310. if (strcmp(midstr2(pstr, b, 3), "REM") == 0 ||
  311. strcmp(midstr2(pstr, b, 1), "'") == 0) break;
  312. f9 = 0;
  313. skip = 0;
  314. for (x9 = b; x9 <= strlen(pstr); x9++)
  315. {
  316. if ((char)(*midstr2(pstr, x9, 1)) == 34)
  317. {
  318. if (f9 == 0)
  319. f9 = 1;
  320. else
  321. f9 = 0;
  322. }
  323. else if (strcmp(midstr2(pstr, x9, 1), ":") == 0 &&
  324. f9 == 0)
  325. {
  326. b1 = x9 - 1;
  327. skip = 1;
  328. break;
  329. }
  330. }
  331. if (skip == 0) b1 = strlen(pstr);
  332. /* GOSub , GOTo , IF. Ken */
  333. t = instr("GOSGOTIF ON RESRET", midstr2(pstr, b, 3));
  334. temp = (t + 5)/3;
  335. if (temp != 1)
  336. {
  337. if (temp == 2 || temp == 3 || temp == 4 || temp == 6 ||
  338. temp == 7)
  339. {
  340. /*-------------------------------------------------*/
  341. /* Change GOSUB, GOTO, IF, RESTORE, RESUME, RETURN */
  342. /* routine. */
  343. /* Go word by word through the statement. */
  344. /*-------------------------------------------------*/
  345. getout = 0;
  346. p8 = b;
  347. strcpy(s9str, " ");
  348. }
  349. else if (temp == 5)
  350. {
  351. /*---------------------------------------------------*/
  352. /* Change ON event/expression GOSUB/GOTO routine. */
  353. /* Find starting point appropriate to this statement */
  354. /* type. */
  355. /*---------------------------------------------------*/
  356. getout = 1;
  357. for (x9 = b1; x9 >= b; x9--)
  358. {
  359. if (strcmp(midstr2(pstr, x9, 1), " ") == 0)
  360. {
  361. p8 = x9 + 1;
  362. getout = 0;
  363. break;
  364. }
  365. }
  366. if (getout == 0) strcpy(s9str, ",");
  367. }
  368. /* Start looping here */
  369. if (getout == 0) while(1)
  370. {
  371. f9 = 0;
  372. skip = 0;
  373. for (x9 = p8; x9 <= b1; x9++)
  374. {
  375. if ((char)(*midstr2(pstr, x9, 1)) == 34)
  376. {
  377. if (f9 == 0)
  378. f9 = 1;
  379. else
  380. f9 = 0;
  381. }
  382. else if (strcmp(midstr2(pstr, x9, 1), s9str) == 0 &&
  383. f9 == 0)
  384. {
  385. p9 = x9 - 1;
  386. skip = 1;
  387. break;
  388. }
  389. }
  390. if (skip == 0) p9 = b1;
  391. skip = 0;
  392. for (x9 = p8; x9 <= p9; x9++)
  393. {
  394. a = (char)(*midstr2(pstr, x9, 1));
  395. if (a < 48 || a > 57)
  396. {
  397. skip = 1;
  398. break;
  399. }
  400. }
  401. if (skip == 0)
  402. {
  403. /*---------------------*/
  404. /* Found a line number */
  405. /*---------------------*/
  406. n = atoi(midstr2(pstr, p8, p9 - p8 + 1));
  407. if (n != 0)
  408. {
  409. if (n >= f6 && n <= l6)
  410. {
  411. binary_search();
  412. if (x == 0)
  413. {
  414. if (p9 == strlen(pstr))
  415. {
  416. strcpy(tempstr, midstr2(pstr, 1, p8 - 1));
  417. strcat(tempstr, rstr);
  418. strcpy(pstr, tempstr);
  419. }
  420. else
  421. {
  422. strcpy(tempstr, midstr2(pstr, 1, p8 - 1));
  423. strcat(tempstr, rstr);
  424. strcat(tempstr, midstr1(pstr, p9 + 1));
  425. strcpy(pstr, tempstr);
  426. }
  427. /*-----------------------------------*/
  428. /* Adjust indices to account for new */
  429. /* substring length, if any. */
  430. /*-----------------------------------*/
  431. d9 = strlen(rstr) - (p9 - p8 + 1);
  432. p9 = p9 + d9;
  433. b1 = b1 + d9;
  434. }
  435. }
  436. }
  437. }
  438. p8 = p9 + 2;
  439. if (p8 > b1) break;
  440. }
  441. }
  442. /*--------------------------------------------------*/
  443. /* No more words to process in the statement, go to */
  444. /* next statement. */
  445. /*--------------------------------------------------*/
  446. if (b1 == strlen(pstr)) break;
  447. b = b1 + 2;
  448. }
  449. }
  450. }
  451. fprintf(fdout, "%s\n", pstr);
  452. if (v1 == 0) printf("%s\n", pstr);
  453. }
  454. fclose(fdin);
  455. fclose(fdout);
  456. /* 11-2019 Ken */
  457. #if !defined(__MVS__) && !defined(__CMS__) && !defined(MSDOS)
  458. tempstr[strlen(tempstr)] = '\0';
  459. sprintf(tempstr, "cp editfl %s", f9str); /* Linux type systems use cp. Ken */
  460. myretn=system(tempstr);
  461. #endif
  462. #if defined(MSDOS)
  463. tempstr[strlen(tempstr)] = '\0';
  464. sprintf(tempstr, "copy editfl %s", f9str); /* MSDOS no cp command. Ken */
  465. myretn=system(tempstr);
  466. #endif
  467. return (0);
  468. }
  469. int instr(astr, bstr)
  470. char *astr, *bstr;
  471. {
  472. char *p;
  473. int q;
  474. p = strstr(astr, bstr);
  475. if (p == NULL)
  476. {
  477. q = 0;
  478. }
  479. else
  480. {
  481. q = (p - astr) + 1;
  482. }
  483. return q;
  484. }
  485. char *midstr1(astr, start)
  486. char *astr;
  487. int start;
  488. {
  489. static char tempstr[MAX_LINE_LENGTH];
  490. char *startptr;
  491. strcpy(tempstr, astr);
  492. startptr = (char *)((long)(tempstr) + start - 1);
  493. return startptr;
  494. }
  495. char *midstr2(astr, start, len)
  496. char *astr;
  497. int start, len;
  498. {
  499. static char tempstr[MAX_LINE_LENGTH];
  500. char *startptr, *endptr;
  501. strcpy(tempstr, astr);
  502. startptr = (char *)((long)(tempstr) + start - 1);
  503. endptr = (char *)((long)(tempstr) + start + len - 1);
  504. strcpy(endptr, "\0");
  505. return startptr;
  506. }
  507. void binary_search(void)
  508. {
  509. int f5, l5;
  510. f5 = f2;
  511. l5 = l2 + 1;
  512. while(1)
  513. {
  514. int m;
  515. m = (f5 + l5)/2;
  516. if (sidx[m][0] == n)
  517. {
  518. rstr[strlen(rstr)] = '\0';
  519. sprintf(rstr, "%d", sidx[m][1]);
  520. x = 0;
  521. return;
  522. }
  523. if (m == f5 || m == l5)
  524. {
  525. x = 1;
  526. return;
  527. }
  528. if (sidx[m][0] < n)
  529. f5 = m;
  530. else
  531. l5 = m;
  532. }
  533. }