Back to index

tetex-bin  3.0
deref.c
Go to the documentation of this file.
00001 /*
00002  * deref.c
00003  *
00004  * Make all texinfo references into the one argument form.
00005  * 
00006  * Arnold Robbins
00007  * arnold@gnu.org
00008  * Written: December, 1991
00009  * Released: November, 1998
00010  *
00011  * Copyright, 1991, 1998 Arnold David Robbins
00012  *
00013  * DEREF is free software; you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation; either version 2 of the License, or
00016  * (at your option) any later version.
00017  * 
00018  * DEREF is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  * 
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program; if not, write to the Free Software
00025  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00026  */
00027 
00028 /*
00029  * LIMITATIONS:
00030  *     One texinfo cross reference per line.
00031  *     Cross references may not cross newlines.
00032  *     Use of fgets for input (to be fixed).
00033  */
00034 
00035 #include <stdio.h>
00036 #include <ctype.h>
00037 #include <errno.h>
00038 
00039 /* for gcc on the 3B1, delete if this gives you grief */
00040 extern int fclose(FILE *fp);
00041 extern int fprintf(FILE *fp, const char *str, ...);
00042 /* extern int sprintf(char *str, const char *fmt, ...); */
00043 extern int fputs(char *buf, FILE *fp);
00044 
00045 extern char *strerror(int errno);
00046 extern char *strchr(char *cp, int ch);
00047 extern int strncmp(const char *s1, const char *s2, int count);
00048 
00049 extern int errno;
00050 
00051 void process(FILE *fp);
00052 void repair(char *line, char *ref, int toffset);
00053 
00054 int Errs = 0;
00055 char *Name = "stdin";
00056 int Line = 0;
00057 char *Me;
00058 
00059 /* main --- handle arguments, global vars for errors */
00060 
00061 int
00062 main(int argc, char **argv)
00063 {
00064        FILE *fp;
00065 
00066        Me = argv[0];
00067 
00068        if (argc == 1)
00069               process(stdin);
00070        else
00071               for (argc--, argv++; *argv != NULL; argc--, argv++) {
00072                      if (argv[0][0] == '-' && argv[0][1] == '\0') {
00073                             Name = "stdin";
00074                             Line = 0;
00075                             process(stdin);
00076                      } else if ((fp = fopen(*argv, "r")) != NULL) {
00077                             Name = *argv;
00078                             Line = 0;
00079                             process(fp);
00080                             fclose(fp);
00081                      } else {
00082                             fprintf(stderr, "%s: can not open: %s\n",
00083                                    *argv, strerror(errno));
00084                             Errs++;
00085                      }
00086               }
00087        return Errs != 0;
00088 }
00089 
00090 /* isref --- decide if we've seen a texinfo cross reference */
00091 
00092 int
00093 isref(char *cp)
00094 {
00095        if (strncmp(cp, "@ref{", 5) == 0)
00096               return 5;
00097        if (strncmp(cp, "@xref{", 6) == 0)
00098               return 6;
00099        if (strncmp(cp, "@pxref{", 7) == 0)
00100               return 7;
00101        return 0;
00102 }
00103 
00104 /* process --- read files, look for references, fix them up */
00105 
00106 void
00107 process(FILE *fp)
00108 {
00109        char buf[BUFSIZ];
00110        char *cp;
00111        int count;
00112 
00113        while (fgets(buf, sizeof buf, fp) != NULL) {
00114               Line++;
00115               cp = strchr(buf, '@');
00116               if (cp == NULL) {
00117                      fputs(buf, stdout);
00118                      continue;
00119               }
00120               do {
00121                      count = isref(cp);
00122                      if (count == 0) {
00123                             cp++;
00124                             cp = strchr(cp, '@');
00125                             if (cp == NULL) {
00126                                    fputs(buf, stdout);
00127                                    goto next;
00128                             }
00129                             continue;
00130                      }
00131                      /* got one */
00132                      repair(buf, cp, count);
00133                      break;
00134               } while (cp != NULL);
00135        next: ;
00136        }
00137 }
00138 
00139 /* repair --- turn all texinfo cross references into the one argument form */
00140 
00141 void
00142 repair(char *line, char *ref, int toffset)
00143 {
00144        int braces = 1;             /* have seen first left brace */
00145        char *cp;
00146 
00147        ref += toffset;
00148 
00149        /* output line up to and including left brace in reference */
00150        for (cp = line; cp <= ref; cp++)
00151               putchar(*cp);
00152 
00153        /* output node name */
00154        for (; *cp && *cp != '}' && *cp != ',' && *cp != '\n'; cp++)
00155               putchar(*cp);
00156 
00157        if (*cp != '}')      {      /* could have been one arg xref */
00158               /* skip to matching right brace */
00159               for (; braces > 0; cp++) {
00160                      switch (*cp) {
00161                      case '@':
00162                             cp++;  /* blindly skip next character */
00163                             break;
00164                      case '{':
00165                             braces++;
00166                             break;
00167                      case '}':
00168                             braces--;
00169                             break;
00170                      case '\n':
00171                      case '\0':
00172                             Errs++;
00173                             fprintf(stderr,
00174                                    "%s: %s: %d: mismatched braces\n",
00175                                    Me, Name, Line);
00176                             goto out;
00177                      default:
00178                             break;
00179                      }
00180               }
00181        out:
00182               ;
00183        }
00184 
00185        putchar('}');
00186        if (*cp == '}')
00187               cp++;
00188 
00189        /* now the rest of the line */
00190        for (; *cp; cp++)
00191               putchar(*cp);
00192        return;
00193 }
00194 
00195 /* strerror --- return error string, delete if in your library */
00196 
00197 char *
00198 strerror(int errno)
00199 {
00200        static char buf[100];
00201        extern int sys_nerr;
00202        extern char *sys_errlist[];
00203 
00204        if (errno < sys_nerr && errno >= 0)
00205               return sys_errlist[errno];
00206 
00207        sprintf(buf, "unknown error %d", errno);
00208        return buf;
00209 }