📄 reader.c
字号:
RTFPanic ("%s: cannot open %s file.", fn, ctrlFileName); /* * Turn off scanner's backslash escape mechanism while reading * file. Restore it later. */ TSGetScanner (&scanner); scanEscape = scanner.scanEscape; scanner.scanEscape = ""; TSSetScanner (&scanner); while (fgets (buf, (int) sizeof (buf), f) != (char *) NULL) { if (buf[0] == '#') /* skip comments */ continue; ++line; TSScanInit (buf); p1 = TSScan (); p2 = TSScan (); p3 = TSScan (); if (line == 1) /* this is the line with the count on it */ { if (p1 == (char *) NULL) /* malformed */ break; nKeys = atoi (p1); rtfCtrl = (RTFCtrl **) RTFAlloc (nKeys * sizeof (RTFCtrl *)); if (rtfCtrl == (RTFCtrl **) NULL) RTFPanic ("%s: out of memory.", fn); for (i = 0; i < nKeys; i++) { rp = (RTFCtrl *) RTFAlloc (sizeof (RTFCtrl)); if (rp == (RTFCtrl *) NULL) RTFPanic ("%s: out of memory.", fn); rtfCtrl[i] = rp; } } else { if (p3 == (char *) NULL) /* malformed */ break; if (line - 1 > nKeys) /* malformed */ break; rp = rtfCtrl[line-2]; rp->major = atoi (p1); rp->minor = atoi (p2); /* reprocess string to remove embedded escapes */ p1 = p2 = p3; while ((c = *p1++) != '\0') { /* * Escaped character. Default is to use next * character unmodified, but \n and \r are * turned into linefeed and carriage return. */ if (c == '\\') { c = *p1++; switch (c) { case 'n': c = '\n'; break; case 'r': c = '\r'; break; } } *p2++ = c; } *p2 = '\0'; if ((rp->str = RTFStrSave (p3)) == (char *) NULL) RTFPanic ("%s: out of memory.", fn); rp->hash = Hash (rp->str); } } scanner.scanEscape = scanEscape; TSSetScanner (&scanner); (void) fclose (f); if (rtfCtrl == (RTFCtrl **) NULL || line - 1 != nKeys) RTFPanic ("%s: %s file contents malformed.", fn, ctrlFileName);}/* * Determine major and minor number of control token. If it's * not found, the class turns into rtfUnknown. */static voidLookup (s)char *s;{RTFCtrl *rp;int hash;int i; ++s; /* skip over the leading \ character */ hash = Hash (s); for (i = 0; i < nKeys; i++) { rp = rtfCtrl[i]; if (hash == rp->hash && strcmp (s, rp->str) == 0) { rtfClass = rtfControl; rtfMajor = rp->major; rtfMinor = rp->minor; return; } } rtfClass = rtfUnknown;}/* * Compute hash value of symbol */static intHash (s)char *s;{char c;int val = 0; while ((c = *s++) != '\0') val += (int) c; return (val);}/* ---------------------------------------------------------------------- *//* * Memory allocation routines *//* * Return pointer to block of size bytes, or NULL if there's * not enough memory available. * * This is called through RTFAlloc(), a define which coerces the * argument to int. This avoids the persistent problem of allocation * failing and causing mysterious crashes under THINK C when a long is * passed. */char *_RTFAlloc (size)int size;{ return ((char *) malloc (size));}/* * Saves a string on the heap and returns a pointer to it. */char *RTFStrSave (s)char *s;{char *p; if ((p = RTFAlloc ((int) (strlen (s) + 1))) == (char *) NULL) return ((char *) NULL); return (strcpy (p, s));}voidRTFFree (p)char *p;{ if (p != (char *) NULL) free (p);}/* ---------------------------------------------------------------------- *//* * Token comparison routines */intRTFCheckCM (class, major)int class, major;{ return (rtfClass == class && rtfMajor == major);}intRTFCheckCMM (class, major, minor)int class, major, minor;{ return (rtfClass == class && rtfMajor == major && rtfMinor == minor);}intRTFCheckMM (major, minor)int major, minor;{ return (rtfMajor == major && rtfMinor == minor);}/* ---------------------------------------------------------------------- */intRTFCharToHex (c)char c;{ if (isupper (c)) c = tolower (c); if (isdigit (c)) return (c - '0'); /* '0'..'9' */ return (c - 'a' + 10); /* 'a'..'f' */}intRTFHexToChar (i)int i;{ if (i < 10) return (i + '0'); return (i - 10 + 'a');}/* ---------------------------------------------------------------------- *//* * RTFReadOutputMap() -- Read output translation map *//* * Read in a file describing the relation between the standard character set * and an RTF translator's corresponding output sequences. Each line consists * of a standard character name and the output sequence for that character. * * outMap is an array of strings into which the sequences should be placed. * It should be declared like this in the calling program: * * char *outMap[rtfSC_MaxChar]; * * reinit should be non-zero if outMap should be initialized before reading the * file, zero otherwise. (This allows the map to be constructed by reading * several files.) It's assumed that any existing strings in the map were * allocated by RTFStrSave(). The map is initialized BEFORE any attempt is * made to read the file. * * If the filename is an absolute pathname, look in the specified location * only. Otherwise try to find the file in the current directory or the * library directory. */intRTFReadOutputMap (file, outMap, reinit)char *file;char *outMap[];int reinit;{FILE *f;char buf[rtfBufSiz];char *name, *seq;int stdCode;int i;TSScanner scanner;char *scanEscape;char *fn = "RTFReadOutputMap"; /* clobber current mapping */ if (reinit) { for (i = 0; i < rtfSC_MaxChar; i++) { RTFFree (outMap[i]); outMap[i] = (char *) NULL; } } if ((f = RTFOpenLibFile (file, "r")) == (FILE *) NULL) return (0); /* * Turn off scanner's backslash escape mechanism while reading * file. Restore it later. */ TSGetScanner (&scanner); scanEscape = scanner.scanEscape; scanner.scanEscape = ""; TSSetScanner (&scanner); /* read file */ while (fgets (buf, (int) sizeof (buf), f) != (char *) NULL) { if(buf[0] == '#') /* skip comment lines */ continue; TSScanInit (buf); if ((name = TSScan ()) == (char *) NULL) continue; /* skip blank lines */ if ((stdCode = RTFStdCharCode (name)) < 0) { RTFMsg ("%s: unknown character name: %s\n", fn, name); continue; } if ((seq = TSScan ()) == (char *) NULL) { RTFMsg ("%s: malformed output sequence line for character %s\n", fn, name); continue; } if ((seq = RTFStrSave (seq)) == (char *) NULL) RTFPanic ("%s: out of memory", fn); outMap[stdCode] = seq; } scanner.scanEscape = scanEscape; TSSetScanner (&scanner); fclose(f); return (1);}/* ---------------------------------------------------------------------- *//* * Open a library file. */static FILE *(*libFileOpen) () = NULL;voidRTFSetOpenLibFileProc (proc)FILE *(*proc) ();{ libFileOpen = proc;}FILE *RTFOpenLibFile (file, mode)char *file;char *mode;{ if (libFileOpen == NULL) return ((FILE *) NULL); return ((*libFileOpen) (file, mode));}/* ---------------------------------------------------------------------- *//* * Print message. Default is to send message to stderr * but this may be overridden with RTFSetMsgProc(). * * Message should include linefeeds as necessary. If the default * function is overridden, the overriding function may want to * map linefeeds to another line ending character or sequence if * the host system doesn't use linefeeds. */static voidDefaultMsgProc (s)char *s;{ fprintf (stderr, "%s", s);}static RTFFuncPtr msgProc = DefaultMsgProc;voidRTFSetMsgProc (proc)RTFFuncPtr proc;{ msgProc = proc;}# ifdef STDARG/* * This version is for systems with stdarg */voidRTFMsg (char *fmt, ...){char buf[rtfBufSiz]; va_list args; va_start (args,fmt); vsprintf (buf, fmt, args); va_end (args); (*msgProc) (buf);}# else /* !STDARG */# ifdef VARARGS/* * This version is for systems that have varargs. */voidRTFMsg (va_alist)va_dcl{va_list args;char *fmt;char buf[rtfBufSiz]; va_start (args); fmt = va_arg (args, char *); vsprintf (buf, fmt, args); va_end (args); (*msgProc) (buf);}# else /* !VARARGS *//* * This version is for systems that don't have varargs. */voidRTFMsg (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)char *fmt;char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9;{char buf[rtfBufSiz]; sprintf (buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); (*msgProc) (buf);}# endif /* !VARARGS */# endif /* !STDARG *//* ---------------------------------------------------------------------- *//* * Process termination. Print error message and exit. Also prints * current token, and current input line number and position within * line if any input has been read from the current file. (No input * has been read if prevChar is EOF). */static voidDefaultPanicProc (s)char *s;{ fprintf (stderr, "%s", s); exit (1);}static RTFFuncPtr panicProc = DefaultPanicProc;voidRTFSetPanicProc (proc)RTFFuncPtr proc;{ panicProc = proc;}# ifdef STDARG/* * This version is for systems with stdarg */voidRTFPanic (char *fmt, ...){char buf[rtfBufSiz]; va_list args; va_start (args,fmt); vsprintf (buf, fmt, args); va_end (args); (void) strcat (buf, "\n"); if (prevChar != EOF && rtfTextBuf != (char *) NULL) { sprintf (buf + strlen (buf), "Last token read was \"%s\" near line %ld, position %d.\n", rtfTextBuf, rtfLineNum, rtfLinePos); } (*panicProc) (buf);}# else /* !STDARG */# ifdef VARARGS/* * This version is for systems that have varargs. */voidRTFPanic (va_alist)va_dcl{va_list args;char *fmt;char buf[rtfBufSiz]; va_start (args); fmt = va_arg (args, char *); vsprintf (buf, fmt, args); va_end (args); (void) strcat (buf, "\n"); if (prevChar != EOF && rtfTextBuf != (char *) NULL) { sprintf (buf + strlen (buf), "Last token read was \"%s\" near line %ld, position %d.\n", rtfTextBuf, rtfLineNum, rtfLinePos); } (*panicProc) (buf);}# else /* !VARARGS *//* * This version is for systems that don't have varargs. */voidRTFPanic (fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)char *fmt;char *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9;{char buf[rtfBufSiz]; sprintf (buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9); (void) strcat (buf, "\n"); if (prevChar != EOF && rtfTextBuf != (char *) NULL) { sprintf (buf + strlen (buf), "Last token read was \"%s\" near line %ld, position %d.\n", rtfTextBuf, rtfLineNum, rtfLinePos); } (*panicProc) (buf);}# endif /* !VARARGS */# endif /* !STDARG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -