#line 1/*ACE 4 0685 */ extern void *malloc(); extern char *suffix(), *basename(), *strdup(); typedef struct flist { char *file; char *name; char *title; int flags; struct flist *next; } FLIST; typedef struct { unsigned version; unsigned headlen; unsigned nplanes; unsigned patlen; unsigned pixelw; unsigned pixelh; unsigned linew; unsigned lines; unsigned palette[16]; } IMGHEADER; typedef unsigned char uchar; typedef unsigned int uint; extern long gemdos(); #define Cconws(s) gemdos(9,s) #define Dsetdrv(d) gemdos(14,d) #define Dsetpath(path) gemdos(59,path) #define Fcreate(fn,mode) gemdos(60,fn,mode) #define Fopen(fn,mode) gemdos(61,fn,mode) #define Fclose(h) gemdos(62,h) #define Fread(h,cnt,buf) gemdos(63,h,cnt,buf) #define Fwrite(h,cnt,buf) gemdos(64,h,cnt,buf) #define Fseek(where,h,how) gemdos(66,where,h,how) #define NL "\r\n" FLIST *FBase = 0L; // Basis der Dateiliste int inhandle; // Handle der aktuellen Eingabedatei uchar inbuf[4096]; // Dateibuffer fuer Eingabe uchar *inptr; long inlen; uchar inpath[128]; // Pfad der Eingabedatei uchar mainpath[128]; // Pfad der Hauptdatei int outhandle; // Handle der Ausgabedatei uchar outbuf[4096]; // Dateibuffer fuer Ausgabe uchar *outptr; uint maxlines; uint Lineno; uchar output[128]; // Name der Ausgabedatei int ExtCnt; int NeedNL; // vor Warnung NL ausgeben int use_filenames; // Dateinamen als nodenamen nutzen int code; int quiet; int NoAuto; char *CurrFile; /* * Fehler melden und terminieren */ Message(str1, str2) char *str1, *str2; { Cconws(str1); if (str2) Cconws(str2); Cconws(NL); } error(s1, s2) char *s1, *s2; { Message(s1, s2); if (outhandle) Fclose(outhandle); if (inhandle) Fclose(inhandle); _exit(1); } /* * Ausgabedatei oeffnen */ Wopen(char *outfile) { if ((outhandle=Fcreate(outfile, 0)) > 5) outptr = outbuf; else error("can't open ", outfile); Lineno = 0; } /* * Datei zum Lesen oeffnen */ Ropen() { register FLIST *p; register char *suf; char tmp[150]; again: p = FBase; while (p) { if (p->flags==0) break; // ersten suchen, der noch p = p->next; // nicht gelesen wurde } if (p == 0L) return(0); // Ende der Liste erreicht p->flags = 1; // als gelesen markieren strcpy(inpath, p->file); // Pfad der Eingabe merken *basename(inpath) = 0; if (*inpath == 0) strcpy(inpath, mainpath); if ((inhandle=Fopen(p->file, 0))<5) // Datei oeffnen error("can't open ", p->file); CurrFile = p->file; if (quiet==0) { Cconws("reading "); Cconws(p->file); Cconws("\033K\r"); NeedNL = 1; } if (p == FBase) { // erste Datei? fputs("@options \"+x -s"); if (NoAuto) fputs("a"); fputs("\"" NL NL); } fputs("@node \""); // Name der Seite strcpy(tmp, p->name); ConvKey(tmp); fputs(tmp); fputs("\""); if (p->title) { // evtl. Titel fputs(" \""); strcpy(tmp, p->title); ConvKey(tmp); fputs(tmp); fputs("\""); } fputs(NL); inlen = -1; inptr = inbuf; // Lesezeiger init. /* * wenn es ein Bild ist, das der HCP lesen kann, * dann binden wir es ein */ suf = suffix(p->file); if (strcmp(suf, ".IMG") == 0) { ImagePage(p); goto again; } return(1); // OK } /* > INF-Datei fr aktuellen 1stGuide-Text lesen */ OpenINF(char *path) { char line[128]; strcpy(line, path); strcpy(suffix(line), ".prj"); if ((inhandle=Fopen(line, 0)) > 0) { inlen = -1; inptr = inbuf; // Lesezeiger init. while (fgets(line)) { fputs(line); fputs(NL); } xclose(inhandle); } } /* * Datei schliessen, dabei evtl. Buffer flushen */ xclose(handle) int handle; { long len; if (handle == outhandle) { len = (long)(outptr-outbuf); if (len) { if (Fwrite(handle, len, outbuf) != len) error("write error", 0L); } } Fclose(handle); } int fgets(line) register uchar *line; { register uchar *p = inptr; int rv = 1, cnt=0; do { if (inlen <= 0L) { inlen = Fread(inhandle, 4096L, inbuf); if (inlen < 0L) // Fehler? error("read error", 0L); if (inlen == 0L) { // nix gelesen? rv = 0; // DateiEnde break; } inptr = p = inbuf; } if (*p == 10) { // NL --inlen; ++p; break; } if (*p != 13) { // CR nicht kopieren *line++ = *p; ++cnt; } --inlen; // einer weniger ++p; } while (cnt<255); *line = 0; // Zeile abschliessen inptr = p; // Pos. naechstes Zeichen return(rv||cnt); // und fertig } fputs(line) register uchar *line; { register uchar *p = outptr; while (*line) { if (*line == '\n') ++Lineno; if ( (long)(p-outbuf) == 4096L) { if (Fwrite(outhandle, 4096L, outbuf) != 4096L) error("write error", 0L); p = outptr = outbuf; } *p++ = *line++; } outptr = p; } /*******************************************************************/ /* * Seitenende erzeugen * Falls Datei zu lang, neue erzeugen */ EndNode() { char file[128]; fputs("@endnode" NL NL NL); xclose(inhandle); // Eingabe schliessen if (maxlines && Lineno>maxlines) { strcpy(file, output); itoa(++ExtCnt, suffix(file)+1, 10); xclose(outhandle); Wopen(file); } } ImagePage(p) FLIST *p; { IMGHEADER *img = (IMGHEADER *)inbuf; uchar *str = inbuf+100; int cnt; Fread(inhandle, (long)sizeof(IMGHEADER), img); cnt = (img->lines+15)/16; fputs("@image "); fputs(p->file); fputs(" 1 "); ltoa((long)((img->linew+7)/8), str, 10); // Breite in Zeichen fputs(str); fputs(" "); ltoa((long)cnt, str, 10); // H”he in Zeichen fputs(str); fputs(NL); EndNode(); } char *Find(char *key) { register FLIST *p; p = FBase; while (p) { if (strcmp(p->name, key)==0) return(0); p = p->next; } return(1); } char *GetName(name, key) char *name, *key; { char buf[20], *rv; /* * wenn gwnscht, dann immer den Dateinamen als * Seitennamen verwenden */ if (use_filenames) { rv = name; goto ende; } if (Find(key)) { // suchen nach Titel rv = key; } else { strcpy(buf, basename(name)); *suffix(buf) = 0; if (Find(buf)) // Datei ohne Endung rv = buf; else { strcpy(buf, basename(name)); if (Find(buf)) // Datei mit Endung rv = buf; else { rv = name; } } } ende: return(strdup(rv)); } #if 0 char *GetName(name, key, flg) char *name, *key; int flg; { register FLIST *p; char buf[20]; register char *new; int flag; flag=0; new = key; // zuerst testen wir das Schlsselwort again: p = FBase; while (p) { if (strcmp(p->name, new) == 0) { if (flag==2) // test auf Dateiname? return(0L); // ja: geht alles nicht chk: ++flag; // war test auf Schlsselwort new = buf; // jetzt probieren wir den Dateinamen strcpy(new, basename(name)); if (flag==1) *suffix(new) = 0; goto again; } p = p->next; } if (flg==0) { flg=1; goto chk; } return(strdup(new)); // gefundenen Nodenamen zurck } #endif /* * Neuen Dateinamen an die Liste zu lesender * Dateien anhaengen, falls sie noch nicht ex. */ FLIST *AddFile(name, key) char *name, *key; { register FLIST *p = FBase, *last = p; while (p) { if (strcmp(p->file, name) == 0) return(p); last = p; p = p->next; } p = malloc(sizeof(FLIST)); if (p == 0L) // Fehler error("out of memory", 0L); p->name = GetName(name, key); p->file = strdup(name); // Namen kopieren if (strcmp(p->name, key)) { // wenn nodename != key p->title = strdup(key); // dann key als Titel nehmen } else p->title = 0L; p->flags = 0; // noch nicht gelesen p->next = 0L; // immer der letzte if (last) { last->next = p; } else { // erstes Element FBase = p; } return(p); } /**********************************************************/ #define IS_ASCII 1 #define NO_TYPE 2 int FileType(file, key) char *file, *key; { char path[128]; register char *p, *save; int h; FLIST *q; /* * Dateinamen in Grožbuchstaben wandeln * und Pfad erg„nzen. */ strupr(file); strcpy(path, inpath); strcat(path, file); /* * Der Pfad k”nnte '..' Teile enthalten, wegen * des Vergleiches der Namen l”schen wir diese * Teile */ again: p = path; save = p; while (*p) { if (*p == '\\') { if (p[1] == '.' && p[2] == '.') { h = *save == '\\' ? 3 : 4; strcpy(save, p+h); goto again; } save = p; // letzter Slash } ++p; } /* * damit die Datei nicht so lang wird, schneiden * wir den Pfad jetzt noch so weit ab, dass er relativ * zur Hauptdatei ist */ save = (char *)mainpath; p = path; while (*p == *save) { ++p; ++save; } strcpy(file, p); p = suffix(file); /* * mal sehen, ob es sich um einen der vom 1stView * untersttzten Dateitypen handelt... * Wenn ja, dann kann der Compiler damit nichts * anfangen (keine ASCII-Datei) und wir liefern * NO_TYPE */ if ( strcmp(p, ".RSC") == 0 || strcmp(p, ".GEM") == 0 || strcmp(p, ".SAM") == 0 || strcmp(p, ".SND") == 0 || strcmp(p, ".OUT") == 0 || strcmp(p, ".DOK") == 0 //- || strcmp(p, ".IMG") == 0 || strcmp(p, ".IFF") == 0 ) return(NO_TYPE); /* * ...dann ist es wohl eine ASCII-Datei; * in diesem Fall wollen wir sie nachher noch lesen, * also kommt sie in die Liste, falls sie ge”ffnet * werden kann */ if ((h=Fopen(file, 0))>0) Fclose(h); else { if (NeedNL) { Cconws(NL); NeedNL = 0; } Cconws("*** warning in '"); Cconws(CurrFile); Message("': missing file ", file); code = 2; return(NO_TYPE); } q = AddFile(file, key); strcpy(file, q->name); return(IS_ASCII); } /* * Sichtbaren Verweis konvertieren */ int ConvKey(key) char *key; { char buf[100]; register char *src = key, *dst = buf; int rv=1; if (*src == '@' || NoAuto) rv=0; // link erzwingen while (*src) { if (*src == '"' || *src == '\\') { *dst++ = '\\'; rv=0; } *dst++ = *src++; } *dst = 0; strcpy(key, buf); return(rv); } int HasBlanks(p) register char *p; { while (*p) { if (*p == ' ') return(1); ++p; } return(0); } DoList() { uchar line[255], buf[512], file[128], key[100]; register uchar *src, *dst, *p; uchar *save; int cnt; while (Ropen()) { // ueber alle Dateien again: while (fgets(line)) { // alle Zeilen src = line; dst = buf; /* * falls die Zeile ein Infoblock ist, dann * ignorieren wir sie einfach */ if (*src == 0x1F) goto again; /* * falls am Anfang ein Kommentarzeichen steht, * rcken wir es einfach ein, damit der Compiler * es ignoriert */ if (*src == '#' && src[1] == '#') *dst++ = ' '; while (*src) { // alle Zeichen switch (*src) { case 0x1C: // streckendes Leerzeichen case 0x1D: // Einzugsleerzeichen case 0x1E: // variables Leerzeichen *dst++ = ' '; ++src; break; case 27: ++src; if (*src>=0x80) { *dst++ = '@'; *dst++ = '{'; *src -= 0x80; if (*src==0) *dst++ = '0'; // alles aus if (*src & 1) *dst++ = 'B'; // Fett if (*src & 2) *dst++ = 'G'; // Hell if (*src & 4) *dst++ = 'I'; // Kursiv if (*src & 8) *dst++ = 'U'; // Underlined *dst++ = '}'; } else { *dst++ = 27; *dst++ = *src; } ++src; break; case '@': *dst++ = '@'; /* fall thru */ default: *dst++ = *src++; break; case 'Ý': p = key; cnt=0; save = dst; do { *dst++ = *src++; if (*src == 'Ý') { *p = 0; if (cnt==1) { ++src; break; } else { p = file; *dst++ = *src++; } ++cnt; } if (*src == 0) goto more; *p++ = *src; } while (1); dst = save; if (FileType(file, key) != IS_ASCII) p = (uchar *)"\\Main"; else { p = 0L; cnt = ConvKey(key); /* * falls der Autoreferenzer diese * Stelle auch alleine findet, lassen * wir ihn das machen */ if (cnt && *src < '0' && dst[-1] < '0' && (HasBlanks(file)==0) && strcmp(key, file) == 0) { strcpy(dst, key); while (*dst++); --dst; break; } } *dst++ = '@'; *dst++ = '{'; *dst++ = '"'; strcpy(dst, key); while (*dst++); --dst; strcpy(dst, "\" link "); dst += 7; ConvKey(file); *dst++ = '"'; strcpy(dst, file); while (*dst++); --dst; if (p) { strcpy(dst, p); while (*dst++); --dst; } *dst++ = '"'; *dst++ = '}'; break; } } more: *dst=0; fputs(buf); fputs(NL); } EndNode(); } } AddIncludes() { char buf[128]; int i; strcpy(buf, output); outhandle = Fopen(buf, 1); outptr = outbuf; Fseek(0L, outhandle, 2); for (i=1; i<=ExtCnt; i++) { strcpy(buf, output); itoa(i, suffix(buf)+1, 10); fputs(NL "@include "); fputs(buf); } fputs(NL); xclose(outhandle); } /**************************************************************/ extern int _argc; extern char **_argv; _main() { main(_argc, _argv); } main(argc, argv) int argc; char **argv; { char outfile[128]; register char *p; int save; maxlines = 0; if (argc < 2) { error("usage: 1stConv [-NNN -f -q -a] file" NL " -NNN: max lines per file" NL " -f : use filenames as nodenames" NL " -q : be quiet" NL " -a : explicit links only" NL , 0L); _exit(1); } save = 0; do { ++argv; --argc; if (**argv == '-') { p = *argv+1; if (*p == 'f') { save = 1; } else if (*p == 'q') ++quiet; else if (*p == 'a') ++NoAuto; else maxlines = atoi(p); } else { if (quiet==0) { Message("1stConv: V(" __DATE__ ") 1stGuide --> ST-Guide sources" NL " Written by Holger Weets using SOZOBON-C V2.00x10" NL , 0L); } /* * Ausgabedatei bestimmen */ strupr(*argv); // falls aus CLI strcpy(outfile, *argv); AddFile(basename(outfile), "Main"); // nur Dateinamen eintragen use_filenames = save; p = (char *)mainpath; // Pfad merken strcpy(p, outfile); *basename(p) = 0; /* * wir setzen das Verzeichnis der Hauptdatei * als aktuelles Verzeichnis, damit die Pfade * relativ angegeben werden k”nnen und somit * die Ausgabedatei krzer und transportabler * wird. */ if (p[1] == ':') Dsetdrv(*p-'A'); Dsetpath(p); strcpy(suffix(outfile), ".stg"); Wopen(outfile); OpenINF(outfile); strcpy(output, outfile); ExtCnt=0; DoList(); xclose(outhandle); if (ExtCnt) AddIncludes(); if (NeedNL) Cconws(NL); break; } } while (argc>1); _exit(code); }