/* Syntax Checker - see manual for specs. Use: <exe file> inputfile Part of HUB MUD Copyright 1995-1997 by Henry McDaniel III. Permisson granted for single user use by and free distribution to persons licensed to use HUB and those they authorize who are presently involved with their implementation of HUB. All other rights reserved. */ #include <stdio.h> #include <ctype.h> /* * Note: you may need to use strings.h on some systems */ #include <string.h> /* * You may need to decrease this number if your machine has * very limit memory. Do NOT raise above 300. * IF you have more than 300 objects, you need to seperate * them into different files. */ #define H_OBJECTS 300 /* CHANGE NOTHING BELOW THIS LINE!!!!!!!!!!!!!!!!!!!!!!!! */ /* ******************************************************* */ #define VERSION "0.0" FILE *fif; int lns = 0; char ln_bu[201]; char mn[30]; #define SBU_TOP 2000 char Sbu[SBU_TOP + 1]; int oco = 0; int start_ln[H_OBJECTS]; int oname[H_OBJECTS][30]; char block_name[30]; #define M_RESET 0 #define M_ID 1 #define M_SHORT 2 #define M_LONG 3 #define M_ANY 4 char tmp_bu[2000]; #define GEM strcpy(tmp_bu,label); \ strcat(tmp_bu," "); strcat(tmp_bu,ln_bu); \ strcpy(ln_bu,tmp_bu); len=strlen(label)+1; int m = 0, sub = 0; int xmapping = 0, xstring = 0, Sstart = 0, fatals = 0, warns = 0; void note (char *text, int ln) { printf ("line %-2d: %s\n", ln, text); } void warn (char *text, int ln) { printf ("line %-2d: Warning, %s\n", ln, text); warns++; } void fatal (char *text, int ln) { printf ("line %-2d: Fatal, %s\n", ln, text); fatals++; } int get_x (char *buf, char *input, int bTOP) { int len, x = 0, y, n = 0, z, bTOPr; while (*(input + x) < 33 || *(input + x) > 125) x++; if (!(len = strlen (input + x))) return 0; bTOPr = bTOP - 1; for (y = x; y < (len + 1) && n <= bTOPr; y++) if (*(input + y) == '\n' || *(input + y) == '\r' || isspace (*(input + y))) break; else { *(buf + n) = *(input + y); n++; } *(buf + n) = '\0'; if (n == bTOPr) return 0; if (y == (len - 1)) return (y + 1); for (z = y; z < len; z++) if (*(input + z) > 32 && *(input + z) < 126) return z; return 0; } int ck_for_dup (char *test) { int TOP = 0, x; char buf[256]; if (oco < 2) return; TOP = oco - 1; for (x = 0; x < TOP; x++) if (!strcmp (test, (char *) oname[x])) { buf[0] = '\0'; sprintf (buf, "object \"%s\" using same id as another", test); warn (buf, lns); if (oco >= 2) note ("original object begins here", start_ln[oco - 2]); else note ("original object ends? around", start_ln[oco - 1]); return 1; } return 0; } int get_obtype (char *test) { char buf[256]; switch (*test) { case 'r': case 'R': return 3; break; case 'n': case 'N': case 'c': case 'C': return 2; break; case 'o': case 'O': return 1; break; } buf[0] = '\0'; sprintf (buf, "unknown or illegal object type %s", test); fatal (buf, lns); return 0; } char label[21]; int get_type (char *name) { if (!strcmp (name, "size") || !strcmp (name, "block") || !strcmp (name, "start") || !strcmp (name, "store") || !strcmp (name, "weight") || !strcmp (name, "capacity") || !strcmp (name, "liquid") || !strcmp (name, "food") || !strcmp (name, "wear") || !strcmp (name, "armor") || !strcmp (name, "point") || !strcmp (name, "decay") || !strcmp (name, "energy") || !strcmp (name, "mob") || !strcmp (name, "level") || !strcmp (name, "ud") || !strcmp (name, "ud") || !strcmp (name, "us") || !strcmp (name, "ld") || !strcmp (name, "ls") || !strcmp (name, "nb")) return 99; if (isdigit (*(label))) if (!strcmp (mn, "block{")) return 99; return 10; } void ast (char *to_add) { int end, x; end = strlen (to_add) - 1; if (!xstring) { Sbu[0] = '\0'; Sstart = lns; } if (*(to_add + end) == '\\') { *(to_add + end) = ' '; *(to_add + end + 1) = '\0'; xstring = 1; if ((end + 2 + strlen (Sbu)) > SBU_TOP) { warn ("string too long", lns); fatal ("possible start of excessive string", Sstart); } } else xstring = 0; strcat (Sbu, to_add); if (!xstring) { x = strlen (Sbu); while (*(Sbu + x) < 33 || *(Sbu + x) > 125) x--; *(Sbu + x + 1) = '\0'; Sbu[0] = '\0'; } } char id[21], type[11], environment[21]; int typen = 0, flags = 0; void pin () { int len = 0, cle = 0, local_type = 0; char ck[11]; char buf[256]; if (xstring) { ast (ln_bu); ln_bu[0] = '\0'; return; } else if (Sbu[0] != '\0') Sbu[0] = '\0'; ck[0] = '\0'; get_x (ck, ln_bu, 10); if (!strcmp (ck, "}") || *ln_bu == '}') { if (!xmapping) warn ("end of mapping mark \"}\" outside of any mapping.", lns); else xmapping = 0; ln_bu[0] = '\0'; return; } switch (m) { case M_ID: id[0] = '\0'; type[0] = '\0'; len = get_x (id, ln_bu, 20); cle += len; len = get_x (type, ln_bu + cle, 10); if (*type == '\0') { fatal ("ID entry missing object type information", lns); exit (0); } cle += len; environment[0] = '\0'; if (len) get_x (environment, ln_bu + cle, 20); if (*environment == '\0') strcpy (environment, "-"); ck_for_dup (id); strcpy ((char *) oname[oco - 1], id); flags = 0; if ((*type == 'c' || *type == 'C') && (*(type + 1) != 'h' && *(type + 1) != 'H')) typen = 1; else typen = get_obtype (type); ln_bu[0] = '\0'; m = M_SHORT; return; break; case M_SHORT: strcpy (label, "short:"); GEM m = M_LONG; break; case M_LONG: strcpy (label, "long:"); GEM m = M_ANY; break; case M_ANY: label[0] = '\0'; len = get_x (label, ln_bu, 20); break; } if (*(label + strlen (label) - 1) == '{') { if (xmapping) fatal ("nested mappings are unsupported.", lns); else { xmapping = 1; strcpy (mn, label); } *(label + strlen (label) - 1) = '\0'; ln_bu[0] = '\0'; return; } else if (*(label + strlen (label) - 1) == ':') { *(label + strlen (label) - 1) = '\0'; local_type = get_type (label); if (local_type != 10) { if (!len) { buf[0] = '\0'; sprintf (buf, "variable \"%s\" without value. will assume %s=0", label, label); warn (buf, lns); } else; ln_bu[0] = '\0'; return; } } else if (*label != '\0') { buf[0] = '\0'; sprintf (buf, "\"%s\" unknown symbol or data.", label); fatal (buf, lns); ln_bu[0] = '\0'; return; } else if (*label == '\0') return; if (len) ast (ln_bu + len); ln_bu[0] = '\0'; } void snooze () { int data_to_process = 0, problem_character = 0, len, x, stop, start = 0; char buf[256]; char load_bu[201]; while (!feof (fif)) { load_bu[0] = '\0'; fgets (load_bu, 200, fif); lns++; if (*load_bu == ';' || *load_bu == '\0') continue; if (*load_bu == '#') { start_ln[oco] = lns; oco++; if (oco > H_OBJECTS) { fatal ("too many objects", lns); buf[0] = '\0'; sprintf (buf, "%d is the maximum of objects per file.", H_OBJECTS); note (buf, lns); exit (0); } m = M_ID; } else { start = 0; len = strlen (load_bu); data_to_process = 0; for (x = 0; x < len && !data_to_process; x++) if (*(load_bu + x) > 32 && *(load_bu + x) < 126) data_to_process = 1; else { start = x; *(load_bu + x) = '\t'; } if (data_to_process) { problem_character = 0; for (x = 0; x < len; x++) if (*(load_bu + x) == 27 || *(load_bu + x) > 126 || *(load_bu + x) == '|') { problem_character = 1; *(load_bu + x) = '?'; } else if (*(load_bu + x) == '\n' || *(load_bu + x) == '\r') *(load_bu + x) = '\0'; if (problem_character) { warn ("illegal character(s) detected and nullified.", lns); note ("illegal chatacter(s) are replaced with \"?\".", lns); } strcpy (ln_bu, load_bu + start); pin (); } } } } void main (int argvc, char **argv) { if (argvc != 2) { printf ("use: %s source\n\r", argv[0]); exit (0); } if (!(fif = fopen (argv[1], "r"))) { printf ("Could not open input file \"%s\"\n\r", argv[1]); exit (0); } mn[0] = '\0'; Sbu[0] = '\0'; printf ("HUB MUD Basic Syntax Checker v%s.\n\ Input file=\"%s\"\n", VERSION, argv[1]); printf ("-----------------------------------------------\n"); snooze (); fclose (fif); printf ("*** %d objects read ***\n", oco); if (warns && fatals) printf ("%d warnings and ", warns); else if (warns) printf ("%d warnings.\n", warns); if (fatals) printf ("%d fatal errors.\n", fatals); if (!warns && !fatals) printf ("No errors.\n"); else printf ("You should fix the indicated problems.\n"); exit (0); }