1 /* 2 * deref.c 3 * 4 * Make all texinfo references into the one argument form. 5 * 6 * Arnold Robbins 7 * arnold@gnu.org 8 * Written: December, 1991 9 * Released: November, 1998 10 * 11 * Copyright, 1991, 1998 Arnold David Robbins 12 * 13 * DEREF is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or 16 * (at your option) any later version. 17 * 18 * DEREF is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 26 */ 27 28 /* 29 * LIMITATIONS: 30 * One texinfo cross reference per line. 31 * Cross references may not cross newlines. 32 * Use of fgets for input (to be fixed). 33 */ 34 35 #include <stdio.h> 36 #include <ctype.h> 37 #include <errno.h> 38 39 /* for gcc on the 3B1, delete if this gives you grief */ 40 extern int fclose(FILE *fp); 41 extern int fprintf(FILE *fp, const char *str, ...); 42 /* extern int sprintf(char *str, const char *fmt, ...); */ 43 extern int fputs(char *buf, FILE *fp); 44 45 extern char *strerror(int errno); 46 extern char *strchr(char *cp, int ch); 47 extern int strncmp(const char *s1, const char *s2, int count); 48 49 extern int errno; 50 51 void process(FILE *fp); 52 void repair(char *line, char *ref, int toffset); 53 54 int Errs = 0; 55 char *Name = "stdin"; 56 int Line = 0; 57 char *Me; 58 59 /* main --- handle arguments, global vars for errors */ 60 61 int 62 main(int argc, char **argv) 63 { 64 FILE *fp; 65 66 Me = argv[0]; 67 68 if (argc == 1) 69 process(stdin); 70 else 71 for (argc--, argv++; *argv != NULL; argc--, argv++) { 72 if (argv[0][0] == '-' && argv[0][1] == '\0') { 73 Name = "stdin"; 74 Line = 0; 75 process(stdin); 76 } else if ((fp = fopen(*argv, "r")) != NULL) { 77 Name = *argv; 78 Line = 0; 79 process(fp); 80 fclose(fp); 81 } else { 82 fprintf(stderr, "%s: can not open: %s\n", 83 *argv, strerror(errno)); 84 Errs++; 85 } 86 } 87 return Errs != 0; 88 } 89 90 /* isref --- decide if we've seen a texinfo cross reference */ 91 92 int 93 isref(char *cp) 94 { 95 if (strncmp(cp, "@ref{", 5) == 0) 96 return 5; 97 if (strncmp(cp, "@xref{", 6) == 0) 98 return 6; 99 if (strncmp(cp, "@pxref{", 7) == 0) 100 return 7; 101 return 0; 102 } 103 104 /* process --- read files, look for references, fix them up */ 105 106 void 107 process(FILE *fp) 108 { 109 char buf[BUFSIZ]; 110 char *cp; 111 int count; 112 113 while (fgets(buf, sizeof buf, fp) != NULL) { 114 Line++; 115 cp = strchr(buf, '@'); 116 if (cp == NULL) { 117 fputs(buf, stdout); 118 continue; 119 } 120 do { 121 count = isref(cp); 122 if (count == 0) { 123 cp++; 124 cp = strchr(cp, '@'); 125 if (cp == NULL) { 126 fputs(buf, stdout); 127 goto next; 128 } 129 continue; 130 } 131 /* got one */ 132 repair(buf, cp, count); 133 break; 134 } while (cp != NULL); 135 next: ; 136 } 137 } 138 139 /* repair --- turn all texinfo cross references into the one argument form */ 140 141 void 142 repair(char *line, char *ref, int toffset) 143 { 144 int braces = 1; /* have seen first left brace */ 145 char *cp; 146 147 ref += toffset; 148 149 /* output line up to and including left brace in reference */ 150 for (cp = line; cp <= ref; cp++) 151 putchar(*cp); 152 153 /* output node name */ 154 for (; *cp && *cp != '}' && *cp != ',' && *cp != '\n'; cp++) 155 putchar(*cp); 156 157 if (*cp != '}') { /* could have been one arg xref */ 158 /* skip to matching right brace */ 159 for (; braces > 0; cp++) { 160 switch (*cp) { 161 case '@': 162 cp++; /* blindly skip next character */ 163 break; 164 case '{': 165 braces++; 166 break; 167 case '}': 168 braces--; 169 break; 170 case '\n': 171 case '\0': 172 Errs++; 173 fprintf(stderr, 174 "%s: %s: %d: mismatched braces\n", 175 Me, Name, Line); 176 goto out; 177 default: 178 break; 179 } 180 } 181 out: 182 ; 183 } 184 185 putchar('}'); 186 if (*cp == '}') 187 cp++; 188 189 /* now the rest of the line */ 190 for (; *cp; cp++) 191 putchar(*cp); 192 return; 193 } 194 195 /* strerror --- return error string, delete if in your library */ 196 197 char * 198 strerror(int errno) 199 { 200 static char buf[100]; 201 extern int sys_nerr; 202 extern char *sys_errlist[]; 203 204 if (errno < sys_nerr && errno >= 0) 205 return sys_errlist[errno]; 206 207 sprintf(buf, "unknown error %d", errno); 208 return buf; 209 } 210