/* * Post-process PC log file format. * * tvb 19-May-2000 */ #include #include #include int IsWhite (char c) { return (c == '\r') || (c == '\n') || (c == ' '); } void Trim (char *s) { while (*s && IsWhite(s[strlen(s) - 1])) { s[strlen(s) - 1] = '\0'; } } void NoCommas (char *s) { char *p; while ((p = strchr(s, ',')) != NULL) { strcpy(p, p + 1); } } /* * Return Modified Julian Day given calendar year, month (1-12), and day (1-31). * - Valid for Gregorian dates from 17-Nov-1858. * - Adapted from sci.astro FAQ. */ long DateToMjd (long Year, long Month, long Day) { return 367 * Year - 7 * (Year + (Month + 9) / 12) / 4 - 3 * ((Year + (Month - 9) / 7) / 100 + 1) / 4 + 275 * Month / 9 + Day + 1721028L - 2400000L; } int Tz; double GetMjd (char *Date, char *Time) { long Year, Month, Day; long Hour, Minute, Second; double Mjd; long Elapsed; int n; n = sscanf(Date, "%ld-%ld-%ld", &Year, &Month, &Day); if (n != 3) { fprintf(stderr, "Invalid date field: %s\n", Date); exit(1); } Mjd = DateToMjd(Year, Month, Day); n = sscanf(Time, "%ld:%ld:%ld", &Hour, &Minute, &Second); if (n != 3) { fprintf(stderr, "Invalid time field: %s\n", Date); exit(1); } Elapsed = ((((Hour - Tz) * 60) + Minute) * 60) + Second; return Mjd + (Elapsed / 86400.0); } struct { long Skip; long Take; long Max; long Avg; long Dp; long MjdDp; double Offset; double Scale; int ShowIndex; int ShowDate; int ShowTime; int ShowMjd; int ShowUnits; char *Units; int Echo; } Opt; const char Usage[] = "\n" " /Skip:# - Skip input data count\n" " /Take:# - Input data count\n" " /Max:# - Maximum output data count\n" "\n" " /Avg:# - Replace every Nth datum with average\n" " /Dp:# - Set number of output decimal places\n" " /Offset:# - Subtract offset from data\n" " /Scale:# - Multiply data by scale\n" "\n" " /Index - Output index numbers\n" " /Date - Output date stamp\n" " /Time - Output time stamp\n" " /All - Output index, date, time\n" " /Mjd - Output computed MJD\n" " /Units: - Set output units\n" " /Tz:# - Set local hours from GMT (e.g., PDT is -7)\n" " /Echo - Echo input lines\n" #if 0 " /Break:# - Insert breaks between sample groups\n" #endif ; int Match (char *Switch, char *Keyword, char **Value) { if (strnicmp(Switch, Keyword, strlen(Keyword)) == 0) { if (Value) { *Value = &Switch[strlen(Keyword)]; } return 1; } return 0; } #define IS_SWITCH(c) ( ((c) == '/') || ((c) == '-') ) void GetOpt (int argc, char *argv[]) { char *Switch; char *Value; Opt.Scale = 1.0; Opt.MjdDp = 5; Opt.Dp = 6; while ((argc > 1) && IS_SWITCH(argv[1][0])) { Switch = &argv[1][1]; if (Match(Switch, "Help", NULL) || Match(Switch, "?", NULL)) { fprintf(stderr, Usage); exit(0); } else if (Match(Switch, "Tz:", &Value)) { Tz = atoi(Value); fprintf(stderr, "TZ = UTC %d\n", Tz); } else if (Match(Switch, "Skip:", &Value)) { Opt.Skip += atol(Value); /* note increment */ fprintf(stderr, "Skip = %ld\n", Opt.Skip); } else if (Match(Switch, "Take:", &Value)) { Opt.Take += atol(Value); /* note increment */ fprintf(stderr, "Take = %ld\n", Opt.Take); } else if (Match(Switch, "Max:", &Value)) { sscanf(Value, "%ld", &Opt.Max); fprintf(stderr, "Max = %ld\n", Opt.Max); } else if (Match(Switch, "Offset:", &Value)) { sscanf(Value, "%lf", &Opt.Offset); fprintf(stderr, "Offset = %g\n", Opt.Offset); } else if (Match(Switch, "Scale:", &Value)) { sscanf(Value, "%lf", &Opt.Scale); fprintf(stderr, "Scale = %g\n", Opt.Scale); } else if (Match(Switch, "Avg:", &Value)) { sscanf(Value, "%ld", &Opt.Avg); fprintf(stderr, "Avg = %ld\n", Opt.Avg); } else if (Match(Switch, "Dp:", &Value)) { sscanf(Value, "%ld", &Opt.Dp); fprintf(stderr, "Dp = %ld\n", Opt.Dp); } else if (Match(Switch, "Index", NULL)) { Opt.ShowIndex ^= 1; } else if (Match(Switch, "Date", NULL)) { Opt.ShowDate ^= 1; } else if (Match(Switch, "Time", NULL)) { Opt.ShowTime ^= 1; } else if (Match(Switch, "Mjd:", NULL)) { sscanf(Value, "%ld", &Opt.MjdDp); fprintf(stderr, "MjdDp = %ld\n", Opt.MjdDp); Opt.ShowMjd = 1; } else if (Match(Switch, "Mjd", NULL)) { Opt.ShowMjd ^= 1; } else if (Match(Switch, "Units:", &Value)) { Opt.Units = Value; fprintf(stderr, "Units = %s\n", Opt.Units); Opt.ShowUnits = 1; } else if (Match(Switch, "All", NULL)) { Opt.ShowIndex = 1; Opt.ShowDate = 1; Opt.ShowTime = 1; #if 0 Opt.ShowUnits = 1; #endif } else if (Match(Switch, "Echo", NULL)) { Opt.Echo = 1; } else { fprintf(stderr, "Unknown option: %s\n", argv[1]); exit(1); } argc -= 1; argv += 1; } } void main (int argc, char *argv[]) { long InCount; long OutCount; char Line[200]; double Count, Sum, Value; GetOpt(argc, argv); InCount = 0; OutCount = 0; Count = 0.0; Sum = 0.0; while (fgets(Line, sizeof(Line), stdin) != NULL) { long Index; char Date[100]; char Time[100]; char Units[100]; int n; /* Delete trailing white space */ /* Echo raw input line */ /* Ignore comment lines */ /* Ignore statistics lines */ /* Remove embedded commas */ Trim(Line); if (Opt.Echo) { printf("%s\n", Line); } if (Line[0] == '#') { continue; } if (strstr(Line, ": ") != NULL) { continue; } NoCommas(Line); /* Extract fields */ n = sscanf(Line, "%ld %s %s %lf %s", &Index, &Date, &Time, &Value, &Units); if (n != 5) { fprintf(stderr, "? Expected 5 fields: %.30s\n", Line); continue; /* exit(1); */ } if (Value == 0.0) { fprintf(stderr, "? Zero value: %.30s\n", Line); continue; /* exit(1); */ } InCount += 1; if (Opt.Skip && InCount <= Opt.Skip) { continue; } if (Opt.Take && InCount > (Opt.Take + Opt.Skip)) { break; } /* Apply offset and scale */ Value -= Opt.Offset; Value *= Opt.Scale; /* Compute average */ if (Opt.Avg) { Sum += Value; Count += 1.0; if (Count < Opt.Avg) { continue; } Value = Sum / Count; Sum = 0.0; Count = 0.0; } /* Display result */ if (Opt.ShowIndex) printf("%ld ", Index); if (Opt.ShowDate) printf("%s ", Date); if (Opt.ShowTime) printf("%s ", Time); if (Opt.ShowMjd) printf("%.*lf ", (int)Opt.MjdDp, GetMjd(Date, Time)); printf("%.*lf", (int)Opt.Dp, Value); if (Opt.ShowUnits) printf(" %s", Opt.Units); printf("\n"); OutCount += 1; if (Opt.Max && OutCount == Opt.Max) { break; } } }