#include #include /* Compiles a .LXT file, producing the .SLG file (SM+ and LM messages) and the .CLG file, containing the CM messages. */ struct _fido fido; _stack = 4000; #define SIZE 1000 /* max. strings per table */ unsigned ptr[SIZE]; /* table of text offsets */ char *text; /* the text blob */ unsigned size; /* it's maximum size */ unsigned highest; /* highest index, per table */ unsigned amt; /* how much in there, per table */ unsigned totl_strings; /* total number of strings */ unsigned totl_size; /* total string size */ char fname[SS]; /* language filename */ int logfile; /* log shit here */ main(argc,argv) int argc; char **argv; { char buff[256],*cp,*op; char et; /* element type */ unsigned en; /* element number */ int in,out; /* file handles */ int phase; /* which pass: LM, SM, CM */ int i,n; unsigned totl_strings,totl_size; printf("FidoText Language File Compiler -- 1 Dec 89\r\n"); printf("Copyright Tom Jennings 1984, 1985, 1986, 1987, 1988, 1989\r\n"); printf("Fido Software, Box 77731, San Francisco CA 94107\r\n"); printf("All rights reserved. \"Fido\", \"FidoNet\" and the\r\n"); printf("dog-with-diskette are registered trademarks of Tom Jennings.\r\n\r\n"); printf("\r\nThis is a restricted use program. Not for distribution.\r\n"); allmem(); fastfile(6); size= sizmem(); if (size < 20000) { printf("Not enough memory to run!\r\n"); exit(1); } text= (char *) getmem(size); /* get working storage */ if (--argc) /* get filename */ cpyarg(fname,*++argv); /* from command line */ else { printf("You have to specify a language filename\r\n"); exit(1); } n= open("fido.sys",0); /* load system stuff */ if (n == -1) { clprintf("The Fido system file \"FIDO.SYS\" is missing!\r\n"); exit(1); } read(n,&fido,sizeof(fido)); close(n); if (fido.fido_version != FIDOVER) { clprintf("Wrong Fido/FidoNet version!\r\n"); exit(1); } /* Pre-process the filename so that we have a clean copy of the name portion around for making the full filename. Basically, lop off any extention and make upper case. */ for (cp= fname; *cp; cp++) { /* remove any extention */ if (*cp == '.') { /* from filename */ *cp= NUL; break; } } stoupper(fname); /* make all upper case */ strcpy(buff,fname); strcat(buff,".LXT"); /* input file name */ in= open(buff,0); if (in == -1) { printf("Can't find \"%s\" input file!\r\n",buff); exit(1); } strcpy(text,fname); strcat(text,".LOG"); logfile= creat(text,2); /* start logging */ clprintf("Log File: %s\r\n",text); clprintf("Input File: %s\r\n",buff); clprintf("Maximum String Size: %8,lu\r\n",0L + size); clprintf("Maximum Table Elements: %8,d\r\n",SIZE); /* Now compile the output file. */ newdelim(" ,\t"); /* the only delimiters */ phase= 'S'; /* from the top */ totl_strings= totl_size= 0; /* zero tally counters */ while (phase != 'X') { switch (phase) { case 'S': out= makeout(".SLG"); wrthdr(out); break; case 'C': out= makeout(".CLG"); wrthdr(out); break; } op= text; /* set output pointer */ amt= highest= 0; /* table index */ lseek(in,0L,0); /* start from the beginning */ for (i= 0; i < SIZE; i++) ptr[i]= 0; /* clear the table */ /* Lines have the format: XMnnn "string" Where X is the element type, and nnn is the element number. */ while (getline(in,buff,sizeof(buff))) { /* read a line */ cp= skip_delim(buff); et= toupper(*cp); /* get element type */ en= atoi(&cp[2]); /* element number */ if ((et == phase) || (et == 'N')) { /* if correct phase */ cp= next_arg(cp); /* skip keyword */ cpyscrarg(op,cp); /* copy, strip quotes */ scrmac(op,op); /* expand controls */ if (en >= SIZE) { clprintf("OOPS -- A numerator is out of range!\r\n"); clprintf("I give up!\r\n"); phase= 'X'; break; } ptr[en]= op - text; /* set it's place in the table */ if (en > highest) highest= en; ++totl_strings; /* count total defined */ i= strlen(op) + 1; /* length of this item */ if (amt + i > size) { clprintf("OOPS -- Total size of text strings is too large!\r\n"); clprintf("I give up!\r\n"); phase= 'X'; break; } amt += i; /* total count */ op += i; /* advance pointer */ totl_size += i; /* total string size */ } } /* End of file -- write the table out. First we have to fixup all the offsets in the pointer table; the table is loaded with the text immediately following; the offsets should be relative to the start of the table. */ ptr[0] += highest * 2; /* 0 is always lang. name */ for (i= 0; i <= highest; i++) { /* add table size to */ if (ptr[i]) /* if defined, */ ptr[i] += highest * 2; /* each str offset */ } write(out,(char *)&ptr[0],highest * 2); /* write table */ if (write(out,text,amt) != amt) { /* then text */ clprintf("OOPS -- Disk full!\r\n"); clprintf("I give up!\r\n"); phase= 'X'; } /* Switch to the next phase. */ switch (phase) { case 'S': /* this phase complete */ clprintf("SM Table String Size: %8,d\r\n",amt); clprintf("Highest Element: SM%03d\r\n",highest); logholes(phase); close(out); phase= 'C'; break; case 'C': clprintf("CM Table String Size: %8,d\r\n",amt); clprintf("Highest Element: CM%03d\r\n",highest); logholes(phase); close(out); phase= 'X'; break; } } clprintf("\r\n"); clprintf("Total String Size: %8,d\r\n",totl_size); clprintf("Total String Elements: %8,d\r\n",totl_strings); close(in); close(logfile); } /* Log all the holes in the table. */ logholes(phase) char phase; { int i,n; for (n= -1, i= 0; i < highest; i++) { if (ptr[i] == 0) { if (n == -1) { clprintf("Unused stringIDs:\r\n"); n= 0; } clprintf("%cM%-3d ",phase,i); if (++n >= 8) { clprintf("\r\n"); n= 0; } } } if (n > 0) clprintf("\r\n"); } /* Write out some junk as a file header. */ wrthdr(f) unsigned f; { char *cp; int i; for (cp= text, i= 256; i--;) *cp++= NUL; /* clear out memory */ strcpy(text,"The contents of this file are Copyright "); strcat(text,"Tom Jennings\Fido Software, San Francisco CA 94107.\r\n"); strcat(text,"All rights reserved. For use with the Fido/FidoNet software "); strcat(text,"system only. This file should not be modified.\r\n"); strcat(text,"\26"); write(f,text,256); /* write out the header */ } /* Get a line from the file; return 0 if the file is empty. */ getline(f,buff,len) int f; char *buff; { char *cp; while (rline(f,buff,len)) { /* read a line of source, */ cp= skip_delim(buff); if (*cp == ';') continue; /* ignore comments */ if (! *cp) continue; /* and blank lines */ return(1); /* got one */ } return(0); /* file empty */ } /* Make and output filename */ makeout(ext) char *ext; { char buff[SS]; int out; strcpy(buff,fname); /* make full name */ strcat(buff,ext); clprintf("\r\n"); printf("Creating output file: \"%s\"\r\n",buff); out= creat(buff,2); if (out == -1) { printf("File creation error!\r\n"); exit(1); } return(out); } /* Copy a script arg; either a single word or a quoted string. */ cpyscrarg(dp,sp) char *dp,*sp; { char lastc,c,q; if (*sp == '"') q= *sp++; else q= NUL; /* optional quote stripping */ lastc= NUL; while (c= *sp) { ++sp; /* next ... */ if ((c == q) && (lastc != '\\')) /* if the quote char & not quoted */ break; /* end of argument */ if (!q && delim(c)) break; /* else stop if a delimiter */ *dp++= c; /* else part of same arg */ lastc= c; /* remember last char */ } *dp= NUL; } /* Convert C-like control characters. */ static scrmac(dp,sp) char *dp,*sp; { char *cp,c; int i; while (c= *sp++) { if (c == '\\') { /* if literal, */ c= *sp; /* get the next char */ if (c) ++sp; /* (dont skip the NUL!) */ switch (tolower(c)) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': c= atoi(--sp); while (isdigit(*sp)) ++sp; break; case 'r': c= CR; break; case 'n': c= LF; break; case 'b': c= BS; break; case 't': c= TAB; break; default: break; /* else leave literal as-is */ } } if (c) *dp++= c; } *dp= NUL; } clprintf(f) char *f; { char buf[400],*p; _spr(buf,&f); p= buf; write (logfile,p,strlen(p)); while (*p) bdos(2,*p++); } /* Return true if the FBIT is set. */ fbit(bit) int bit; { return(fido.fbits[bit / sizeof(char)] & (1 << bit % sizeof(char))); }