pchmaker.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  1. /*
  2. * GTools C compiler
  3. * =================
  4. * source file :
  5. * Pre-Compiled Header maker code
  6. */
  7. /* NOTE : this source file is completely awful, but PchMaker was originally
  8. * designed to be used only internally */
  9. #include "define.h"
  10. #include "pch.h"
  11. #define SHARED /* we'll generate extra info so shared headers are possible */
  12. FILE *src=0,*pch=0;
  13. char *in=0;
  14. #ifdef SHARED
  15. #include <malloc.h>
  16. char *defname=0;
  17. int n_ignored=0; char **ignored[20];
  18. #endif
  19. void fail(char *s) {
  20. #ifdef PC
  21. printf(s);
  22. printf("\n");
  23. #else
  24. clrscr();
  25. printf(s);
  26. ngetchx();
  27. #endif
  28. }
  29. void skipspace() {
  30. char c;
  31. while ((c=*in)==' ' || c=='\n' || c=='\t') in++;
  32. }
  33. #ifdef PC
  34. #define N_MAX 4096
  35. #else
  36. #define N_MAX 1024
  37. #endif
  38. char *tab[N_MAX];
  39. int N=0,var_size=0;
  40. int extSz[N_MAX];
  41. int extCumSz[N_MAX];
  42. void *extDat[N_MAX];
  43. int nExt=0;
  44. /*#ifdef PC*/
  45. void wri(char *p,int v) {
  46. *p++=(char)(v>>8);
  47. *p=(char)v;
  48. }
  49. void addwri(char *p,int v) {
  50. (*p++)+=(char)(v>>8);
  51. (*p) +=(char)v;
  52. }
  53. int rd(unsigned char *p) {
  54. return (((int)*p)<<8)+p[1];
  55. }
  56. /*#else
  57. #define wri(p,v) *(short *)(p)=v
  58. #define rd(p) (*(short *)(p))
  59. #endif*/
  60. #ifdef PC
  61. void maj_conv(char *s) {
  62. char c;
  63. while ((c=*s++))
  64. if (c>='A' && c<='Z')
  65. memmove(s+1,s,strlen(s)+1), *s='-';
  66. }
  67. #endif
  68. char *defPack(char *s);
  69. char *sPack(char *s,char *name,char *defn);
  70. #ifdef PC
  71. int memname,memdefn,meminit,memispk;
  72. #endif
  73. int argslen(char *s) {
  74. char *p=s;
  75. while (*p) { /* skip each argument */
  76. while (*p++);
  77. }
  78. return (int)((long)p)-(int)((long)s);
  79. }
  80. #ifdef PC
  81. #define LOGGING
  82. #endif
  83. extern char *sPk_table;
  84. #ifdef PC
  85. static char __sPk_tab[3000];
  86. #ifdef PC
  87. int sPk_usetab[128]={0};
  88. #endif
  89. #define __sPk_end (&__sPk_tab[3000])
  90. void read_spack_table(int init) {
  91. FILE *fp=fopen("lex.txt","r");
  92. char buf[100]; int n; char *p;
  93. if (!fp) { if (init) printf("Warning : can't open lex file\n"); sPk_table="\0"+1; return; }
  94. __sPk_tab[0]=0; /* sPack requires sPk_table[-1] to be 0 */
  95. sPk_table=__sPk_tab+1;
  96. sPk_table[0]=0; /* so that the empty string always comes last :) */
  97. while (!feof(fp)) {
  98. p=sPk_table;
  99. fgets(buf,100,fp);
  100. n=strlen(buf);
  101. if (buf[n-1]=='\n') n--, buf[n]=0;
  102. while (strcmp(p,buf)>0) /* perform a decreasing insertion sort */
  103. while (*p++);
  104. memmove(p+n+1,p,__sPk_end-(p+n+1));
  105. strcpy(p,buf);
  106. }
  107. if (init)
  108. memset(sPk_usetab,128,0);
  109. else {
  110. p=sPk_table; n=0;
  111. while (*p) {
  112. if (!sPk_usetab[n])
  113. memmove(p,p+strlen(p)+1,__sPk_end-p), n++;
  114. else { while (*p++); n++; }
  115. }
  116. }
  117. }
  118. #else
  119. void read_spack_table() {
  120. sPk_table="\0"+1;
  121. }
  122. #endif
  123. int get_spack_table_size() {
  124. char *p=sPk_table;
  125. while (*p)
  126. while (*p++);
  127. return (int)(p+1-sPk_table);
  128. }
  129. int hdr_read() {
  130. char c,cont=1;
  131. #ifdef LOGGING
  132. FILE *logfp=fopen("pchlog.txt","w");
  133. #endif
  134. var_size=0;
  135. skipspace();
  136. if (strncmp(in,"#var ",4)) {
  137. fail("'#var' expected");
  138. return 0;
  139. }
  140. in+=4;
  141. while (cont) {
  142. char *name,*args=NULL,*defn,*init,*block,*ptr;
  143. #ifdef PC
  144. int extID=-1; int oldinit=0;
  145. #endif
  146. char **tp,**tp0;
  147. int A,B,C,D,n/*,*ip*/; unsigned int flags=0;
  148. skipspace();
  149. if (!*in) return;
  150. name=in;
  151. while ((c=*in)!=' ' && c!='\n' && c!='\t' && c!='(') {
  152. if (c=='.') *in=' ';
  153. in++;
  154. }
  155. if (c=='(') {
  156. flags|=PCHID_MACRO;
  157. *in++=0;
  158. args=in;
  159. while ((c=*in)!=')')
  160. if (c==',') *in++=0; /* terminate string */
  161. else if (c=='.') *in++=0, flags|=PCHID_VAMAC; /* terminate macro */
  162. else in++;
  163. *in++=0; /* terminate macro */
  164. if ((c=*in)!=' ' && c!='\n' && c!='\t') { fail("space expected"); return 0; }
  165. }
  166. *in=0; defn=in; in++;
  167. skipspace();
  168. if (*in=='D' && in[1]=='(') {
  169. int depth=0; char c;
  170. in+=2; defn=in;
  171. while ((c=*in++)) {
  172. if (c=='(') depth++;
  173. else if (c==')') { if (--depth<0) break; }
  174. }
  175. in[-1]=0;
  176. if (!c) in--;
  177. if (depth>=0) {
  178. printf("\n**************\n*** ERROR! ***\n**************\nUnmatched '('\n");
  179. return 0;
  180. }
  181. }
  182. /* if (*in=='M' && in[1]=='(') {
  183. int depth=0; char c;
  184. in+=2; defn=in;
  185. while ((c=*in++)) {
  186. if (c=='(') depth++;
  187. else if (c==')') { if (--depth<0) break; }
  188. }
  189. in[-1]=0;
  190. is_macro=(char)0x80;
  191. }*/
  192. defn=defPack(defn);
  193. if (def_is_packed) flags|=PCHID_PACKED;
  194. #ifdef LOGGING
  195. fputs(defn,logfp);
  196. fputc('\n',logfp);
  197. #endif
  198. skipspace();
  199. init=in;
  200. if (!*in) { cont=0; goto write_it; }
  201. while (*in && (*in!='#' || strncmp(in,"#var ",4))) in++;
  202. while ((c=*--in)==' ' || c=='\n' || c=='\t'); // remove trailing whitespace
  203. in++;
  204. cont=*in;
  205. *in=0;
  206. if (in<init) init=in;
  207. in++;
  208. skipspace();
  209. if (!*in) cont=0;
  210. in+=4;
  211. #ifdef PC
  212. oldinit=strlen(init);
  213. #endif
  214. init=sPack(init,name,defn);
  215. write_it:
  216. #ifdef SHARED
  217. { int i;
  218. for (i=0;i<n_ignored;i++) {
  219. char **p=ignored[i];
  220. while (*p)
  221. if (!strcmp(name,*p++))
  222. goto _continue;
  223. }
  224. }
  225. #endif
  226. #ifdef PC
  227. { char b[100]; FILE *tfp;
  228. sprintf(b,"a2ext\\%s.ref",name);
  229. maj_conv(b);
  230. tfp=fopen(b,"r");
  231. if (tfp) {
  232. void *buf; int sz,i; int *szp=extSz; void **edp=extDat;
  233. unsigned char sz_buf[2];
  234. fgets(b+(sizeof("a2ext\\")-1),100,tfp);
  235. fclose(tfp);
  236. tfp=fopen(b,"rb"); /* open the .ext file */
  237. if (!tfp) { printf("Couldn't find .ext file\n"); goto ext_ok; }
  238. if (fread(sz_buf,1,2,tfp)!=2) { printf("Bad .ext file\n"); goto ext_ok; }
  239. sz=(sz_buf[0]<<8)+sz_buf[1];
  240. buf=malloc(sz+1);
  241. if ((int)fread(buf,1,sz+1,tfp)!=sz) { printf("Bad .ext file\n"); goto ext_ok; }
  242. fclose(tfp);
  243. i=nExt; extID=0;
  244. while (i--) {
  245. if (*szp++==sz && !memcmp(*edp,buf,sz)) {
  246. free(buf);
  247. goto ext_ok;
  248. }
  249. edp++; extID++;
  250. }
  251. nExt++;
  252. if (!extID) *extCumSz=0;
  253. else extCumSz[extID]=extCumSz[extID-1]+szp[-1];
  254. *szp=sz; *edp=buf;
  255. ext_ok:
  256. (void)0;
  257. }
  258. }
  259. #endif
  260. A=strlen(name);
  261. if (args) B=argslen(args); else B=-1;
  262. C=strlen(defn); D=strlen(init);
  263. n=(A+1)+2*3+(B+1)+(C+1)+(D+1)+1;
  264. ptr=block=4+(char *)malloc(4+n);
  265. memset(ptr,0,n);
  266. wri((char *)((short *)ptr-1),n);
  267. // wri((char *)((short *)ptr-2),0);
  268. memcpy(ptr,name,A);
  269. ptr+=(A+1)+2*3;
  270. ptr[-2]=flags>>8;
  271. if (B>0) memcpy(ptr,args,B);
  272. memcpy(ptr+=(B+1),defn,C);
  273. memcpy(ptr+=(C+1),init,D);
  274. #ifdef PC
  275. *(ptr+(D+1))=extID+1;
  276. #else
  277. *(ptr+(D+1))=0;
  278. #endif
  279. tp=tab;
  280. while (strcmp(*tp,block)<0) tp++;
  281. if (!strcmp(*tp,block)) {
  282. if (memcmp(*tp,block,n)) {
  283. printf("Warning:Redeclaration of %s\n",name);
  284. } else {
  285. free(block-4);
  286. continue;
  287. }
  288. }
  289. var_size+=n;
  290. #ifdef PC
  291. memname+=A+1,memdefn+=C+1,memispk+=D+1;
  292. meminit+=oldinit+1;
  293. #endif
  294. tp0=tp;
  295. /* ip=(int *)*tp;
  296. ((int *)block)[-2]=ip[-2];
  297. tp--;
  298. do {
  299. tp++;
  300. ip=(int *)*tp;
  301. ip[-2]+=n;
  302. } while (**tp!='ÿ');*/
  303. memmove(tp0+1,tp0,N_MAX*sizeof(char *)+((long)tab)-((long)tp0));
  304. *tp0=block;
  305. N++;
  306. if (N>=N_MAX) { printf("Too many IDs."); return 0; }
  307. _continue:
  308. ;
  309. }
  310. #ifdef LOGGING
  311. fclose(logfp);
  312. #endif
  313. #ifdef SHARED
  314. {
  315. FILE *fp=fopen(defname,"w");
  316. if (fp) {
  317. int n=N; char **tp=tab;
  318. while (n--)
  319. fprintf(fp,"%s\n",*tp++);
  320. fclose(fp);
  321. } else {
  322. printf("Can't open .def file");
  323. return 0;
  324. }
  325. }
  326. #endif
  327. return 1;
  328. }
  329. int written=0,pswritten[N_MAX]={0};
  330. #ifdef PC
  331. int dtot=0,dnum=0;
  332. int dhtot=0,dhnum=0;
  333. #endif
  334. int do_write(int a,int b,int real,int psw
  335. #ifdef PC
  336. ,int depth
  337. #endif
  338. ) {
  339. if (a<=b) {
  340. int i=(a+b)/2,sz=rd((char *)((short *)tab[i]-1));
  341. int x=do_write(a,i-1,0,psw+sz
  342. #ifdef PC
  343. ,0
  344. #endif
  345. ),y=do_write(i+1,b,0,x
  346. #ifdef PC
  347. ,0
  348. #endif
  349. );
  350. if (real) {
  351. char *t=tab[i];
  352. while (*t++);
  353. wri((char *)((short *)t+0),x==psw+sz?0:psw+sz);
  354. wri((char *)((short *)t+1),y==x?0:x);
  355. addwri((char *)((short *)t+2),i-1);
  356. fwrite(tab[i],1,sz,pch);
  357. written+=sz;
  358. // pswritten=written;
  359. #ifdef PC
  360. dtot+=depth; dnum++;
  361. if (x==psw+sz/*) dhtot+=depth, dhnum++;
  362. if (*/ || y==x) dhtot+=depth, dhnum++;
  363. #endif
  364. do_write(a,i-1,1,psw+sz
  365. #ifdef PC
  366. ,depth+1
  367. #endif
  368. ),do_write(i+1,b,1,x
  369. #ifdef PC
  370. ,depth+1
  371. #endif
  372. );
  373. return 0;
  374. } else
  375. /* if (((int *)tab[i])[-2]!=written)
  376. printf("Error, written=%d and offset=%d\n",written,((int *)tab[i])[-2]);*/
  377. return y;
  378. } else return psw;
  379. }
  380. #ifdef PC
  381. void _fw16(unsigned short x,FILE *fp) {
  382. fputc((unsigned char)(x>>8),fp);
  383. fputc((unsigned char)x,fp);
  384. }
  385. #define fw16(x,f) _fw16((unsigned short)(x),f)
  386. #endif
  387. void pch_write() {
  388. int n,extOff,dicOff;
  389. int *szp=extSz,*cszp=extCumSz; void **edp=extDat;
  390. int sPk_size=get_spack_table_size();
  391. fwrite("PCH\0" "\0\0",PCH_HEAD_SIZE-6,1,pch);
  392. dicOff=PCH_HEAD_SIZE+var_size;
  393. extOff=dicOff+sPk_size;
  394. extOff+=(extOff&1);
  395. fw16(extOff,pch);
  396. fw16(dicOff,pch);
  397. fw16(N-1,pch);
  398. do_write(1,N-1,1,PCH_HEAD_SIZE
  399. #ifdef PC
  400. ,1
  401. #endif
  402. );
  403. fwrite(sPk_table,1,sPk_size,pch);
  404. extOff+=nExt*2;
  405. if ((dicOff+sPk_size)&1) fputc(0,pch);
  406. n=nExt; while (n--) fw16(extOff+(*cszp++),pch);
  407. n=nExt;
  408. while (n--)
  409. fwrite(*edp++,1,*szp++,pch);
  410. #ifndef PC
  411. fwrite("\0HDR\0\xF8",6,1,pch);
  412. #endif
  413. printf("Success!\n");
  414. }
  415. char sym0[9]={0};
  416. #ifdef PC
  417. int main(int argc,char **argv) {
  418. char *srcname,*pchname; char pchbuf[200],defbuf[200];
  419. int quiet=0;
  420. int error = 0;
  421. #ifdef SHARED
  422. while (argc>=2 && argv[1][0]=='-') {
  423. if (argv[1][1]=='i') {
  424. FILE *fp=fopen(argv[1]+2,"r");
  425. char lbuf[200],*lptr; int l_n=0;
  426. char *lnbuf[2000],**lnptr;
  427. if (!fp) {
  428. fail("Can't open .def file");
  429. return 254;
  430. }
  431. while (!feof(fp)) {
  432. fgets(lbuf,190,fp);
  433. lbuf[strlen(lbuf)-1]=0; // strip \n
  434. if (!*lbuf) continue;
  435. lptr=alloca(strlen(lbuf)+1);
  436. strcpy(lptr,lbuf);
  437. lnbuf[l_n++]=lptr;
  438. }
  439. lnbuf[l_n++]=0;
  440. lnptr=alloca(l_n*sizeof(char*));
  441. memcpy(lnptr,lnbuf,l_n*sizeof(char*));
  442. ignored[n_ignored++]=lnptr;
  443. fclose(fp);
  444. argv++; argc--;
  445. } else if (argv[1][1]=='q') {
  446. quiet=1;
  447. argv++; argc--;
  448. } else break;
  449. }
  450. #endif
  451. if (argc!=2 && argc!=3) {
  452. fail("Syntax : pchmaker [-i<pch1> ... -i<pchN>] [-q] <in> [<out>]\n");
  453. return 255;
  454. }
  455. srcname=argv[1];
  456. if (strlen(srcname)>=200-4-1) {
  457. fail("File name is too long\n");
  458. return 254;
  459. }
  460. if (argc==2) {
  461. char *dot_ptr = strrchr(srcname,'.');
  462. int dot = dot_ptr ? dot_ptr-srcname : strlen(srcname);
  463. strcpy(pchname=pchbuf,srcname), strcpy(pchname+dot,".pch");
  464. #ifdef SHARED
  465. strcpy(defname=defbuf,srcname), strcpy(defname+dot,".def");
  466. #endif
  467. } else pchname=argv[2];
  468. #else
  469. #include <estack.h>
  470. void _main(void) {
  471. char *srcname,pchname[30];
  472. int error = 0;
  473. srcname=top_estack;
  474. if (*srcname!=STR_TAG) {
  475. fail("Usage: pchmaker(\"infile\")");
  476. return;
  477. }
  478. srcname--;
  479. while (*--srcname);
  480. srcname++;
  481. sprintf(pchname,"zheader\\%s",srcname);
  482. #endif
  483. src=fopen(srcname,"r");
  484. pch=fopen(pchname,"wb");
  485. if (!src || !pch) {
  486. fail("Couldn't open file");
  487. if (src) fclose(src);
  488. return;
  489. }
  490. #ifndef PC
  491. in=*(char **)src;
  492. #else
  493. in=malloc(100000);
  494. in[fread(in,1,100000,src)]=0;
  495. #endif
  496. /*pswritten=*/written=4;
  497. N=1;
  498. memset(sym0,0,9);
  499. sym0[3]=5;
  500. tab[0]=4+sym0;
  501. tab[1]=4+"\0\6\0\0ÿ";
  502. read_spack_table(1);
  503. if (hdr_read()) {
  504. #ifdef PC
  505. #define clr(x) mem##x=0
  506. clr(name),clr(defn),clr(ispk),clr(init);
  507. fseek(src,0,SEEK_SET);
  508. in=malloc(100000);
  509. in[fread(in,1,100000,src)]=0;
  510. written=4;
  511. N=1;
  512. memset(sym0,0,9);
  513. sym0[3]=5;
  514. tab[0]=4+sym0;
  515. tab[1]=4+"\0\6\0\0ÿ";
  516. read_spack_table(0);
  517. hdr_read();
  518. #endif
  519. #ifdef PC
  520. dnum=dtot=0;
  521. dhnum=dhtot=0;
  522. #endif
  523. pch_write();
  524. #ifdef PC
  525. if (!quiet) {
  526. #define disp(x) printf("Memory used by '" #x "' : %5d bytes\n", mem##x)
  527. printf("Header contains %d identifiers\n",N-1);
  528. printf("Average tree depth : %f\n",((float)dtot)/dnum); /* depth if ID is in PCH */
  529. printf("Average leaf depth : %f\n",((float)dhtot)/dhnum); /* depth if ID not found */
  530. printf("\n");
  531. disp(name),disp(defn),disp(ispk),disp(init);
  532. printf("\nHeader has %d extension%s\n",nExt,nExt==1?"":"s");
  533. printf("Memory used by extensions : %5d bytes\n", extCumSz[nExt-1]+extSz[nExt-1]);
  534. }
  535. #endif
  536. } else
  537. error = 1;
  538. fclose(pch);
  539. fclose(src);
  540. return error;
  541. }