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